
تجاوز سعة المخزن المؤقت للكومة في GNOME gThumb و Linux Mint Pix
يستخدم كل من GNOME gThumb و Linux Mint Pix وحدة cairo_io لعرض عدة تنسيقات للصور باستخدام مكتبة الرسوميات Cairo. في إصدارات gThumb الأقل من 3.8.3 وإصدارات Pix الأقل من 2.4.5، تكون cairo_io معرضة لخطأ تجاوز سعة المخزن المؤقت على الكومة عبر صورة JPEG يكون فيها إما العرض أو الارتفاع أكبر من 32767 بكسل. توجد الثغرة في الدالة _cairo_image_surface_create_from_jpeg() من extensions/cairo_io/cairo-image-surface-jpeg.c.
تدعم cairo_io أقصى أبعاد JPEG وهي 32767 × 32767 (CAIRO_MAX_IMAGE_SIZE).1 عند تخصيص سطح Cairo، بالنسبة لكل من العرض والارتفاع، تختار _cairo_image_surface_create_from_jpeg() القيمة الأصغر بين CAIRO_MAX_IMAGE_SIZE والطول المحدد في مقطع SOF0 للملف. على سبيل المثال، إذا ادعى ملف JPEG أن حجمه 40000 × 30000، فستقوم cairo_io بتخصيص كائن cairo_surface_t صالح فقط لـ 32767 × 30000 بكسل.
في المقتطف أدناه، srcinfo.output_width و srcinfo.output_height هما أبعاد الصورة الأصلية، بينما destination_width و destination_height هما الأبعاد المحدودة. الأبعاد الأخيرة هي التي تُمرر إلى _cairo_image_surface_create() لإنشاء السطح.2
_cairo_image_surface_transform_get_steps (CAIRO_FORMAT_ARGB32,
MIN (srcinfo.output_width, CAIRO_MAX_IMAGE_SIZE),
MIN (srcinfo.output_height, CAIRO_MAX_IMAGE_SIZE),
orientation,
&destination_width,
&destination_height,
&line_start,
&line_step,
&pixel_step);
// ...
surface = _cairo_image_surface_create (CAIRO_FORMAT_ARGB32, destination_width, destination_height);
ومع ذلك، عند كتابة بيانات البكسل في السطح المخصص، تقوم _cairo_image_surface_create_from_jpeg() بالتكرار على الأبعاد الأصلية المحددة بواسطة JPEG، srcinfo.output_width و srcinfo.output_height، بدلاً من الأبعاد المناسبة destination_width و destination_height. هيكل الحلقة المتداخلة أدناه يحدث في خمسة مواقع من ملف cairo-image-surface-jpeg.c كل منها يعالج نوعًا مختلفًا من فراغ اللون.3 4 5 6 7
while (srcinfo.output_scanline < srcinfo.output_height) {
// ...
for (x = 0; x < srcinfo.output_width; x++) {
// ...
memcpy (p_surface, &pixel, sizeof (guint32));
نظرًا لأن أبعاد JPEG الأصلية قد تكون أكبر من منطقة الذاكرة المخصصة للسطح، يمكن أن يؤدي هذا التناقض إلى كتابة بيانات بكسل يتحكم بها المهاجم خارج حدود المخزن المؤقت data لهيكل cairo_surface_t.
انظر حالة الاختبار المصغرة، poc.min.jpg. هذا الملف حجمه 107 بايت ويحدد أبعادًا 1 × 33000.
$ gthumb ./poc.min.jpg
=================================================================
==20729==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x7f49fdc587fc at pc 0x7f4a12200534 bp 0x7f49fe46e240 sp 0x7f49fe46e230
WRITE of size 4 at 0x7f49fdc587fc thread T5 (pool-gthumb)
#0 0x7f4a12200533 in _cairo_image_surface_create_from_jpeg ../extensions/cairo_io/cairo-image-surface-jpeg.c:372
#1 0x55b8e24aad9b in load_image_thread ../gthumb/gth-image-loader.c:241
#2 0x7f4a1a1a5d21 (/lib/x86_64-linux-gnu/libgio-2.0.so.0+0xb2d21)
#3 0x7f4a1a34f853 (/lib/x86_64-linux-gnu/libglib-2.0.so.0+0x7b853)
#4 0x7f4a1a34f110 (/lib/x86_64-linux-gnu/libglib-2.0.so.0+0x7b110)
#5 0x7f4a19668668 in start_thread /build/glibc-4WA41p/glibc-2.30/nptl/pthread_create.c:479
#6 0x7f4a19590322 in clone (/lib/x86_64-linux-gnu/libc.so.6+0x122322)
0x7f49fdc587fc is located 0 bytes to the right of 131068-byte region [0x7f49fdc38800,0x7f49fdc587fc)
allocated by thread T5 (pool-gthumb) here:
#0 0x7f4a1a658ce6 in calloc (/lib/x86_64-linux-gnu/libasan.so.5+0x10dce6)
#1 0x7f4a18aba5a1 (/lib/x86_64-linux-gnu/libpixman-1.so.0+0x1a5a1)
Thread T5 (pool-gthumb) created by T0 here:
#0 0x7f4a1a585805 in pthread_create (/lib/x86_64-linux-gnu/libasan.so.5+0x3a805)
#1 0x7f4a1a371a16 (/lib/x86_64-linux-gnu/libglib-2.0.so.0+0x9da16)
SUMMARY: AddressSanitizer: heap-buffer-overflow ../extensions/cairo_io/cairo-image-surface-jpeg.c:372 in _cairo_image_surface_create_from_jpeg
Shadow bytes around the buggy address:
0x0fe9bfb830a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0fe9bfb830b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0fe9bfb830c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0fe9bfb830d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0fe9bfb830e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0fe9bfb830f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00[04]
0x0fe9bfb83100: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0fe9bfb83110: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0fe9bfb83120: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0fe9bfb83130: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0fe9bfb83140: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
Shadow gap: cc
==20729==ABORTING