Goal Reached Thanks to every supporter — we hit 100%!

Goal: 1000 CNY · Raised: 1359 CNY

100%

CVE-2019-20326 PoC — GNOME gThumb和Linux Mint Pix 缓冲区错误漏洞

Source
Associated Vulnerability
Title: GNOME gThumb和Linux Mint Pix 缓冲区错误漏洞 (CVE-2019-20326)
Description:A heap-based buffer overflow in _cairo_image_surface_create_from_jpeg() in extensions/cairo_io/cairo-image-surface-jpeg.c in GNOME gThumb before 3.8.3 and Linux Mint Pix before 2.4.5 allows attackers to cause a crash and potentially execute arbitrary code via a crafted JPEG file.
Description
Heap buffer overflow in GNOME gThumb and Linux Mint Pix
Readme
# CVE-2019-20326

GNOME gThumb and Linux Mint Pix use the `cairo_io` module for displaying several image formats with the Cairo graphics library. In gThumb versions < 3.8.3 and Pix versions < 2.4.5, `cairo_io` is vulnerable to a heap buffer overflow via a JPEG image with either a width or height greater than 32767 pixels. The vulnerability exists in the function [`_cairo_image_surface_create_from_jpeg()`](https://github.com/GNOME/gthumb/blob/0c0f0300d54d050ca87d23de4c734c24f37e8958/extensions/cairo_io/cairo-image-surface-jpeg.c#L144) from `extensions/cairo_io/cairo-image-surface-jpeg.c`.

`cairo_io` supports maximum JPEG dimensions of 32767 x 32767 (`CAIRO_MAX_IMAGE_SIZE`).<sup>1</sup> When allocating a Cairo surface, for both the width and height, `_cairo_image_surface_create_from_jpeg()` picks the minimum of `CAIRO_MAX_IMAGE_SIZE` and the length specified in the SOF0 segment of the file. For example, if a JPEG file claims to have a size of 40000 x 30000, `cairo_io` will allocate a `cairo_surface_t` object valid for only 32767 x 30000 pixels.

In the snippet below, `srcinfo.output_width` and `srcinfo.output_height` are the original image dimensions, while `destination_width` and `destination_height` are the capped dimensions. The latter are the ones passed to `_cairo_image_surface_create()` for surface creation.<sup>2</sup>

```c
_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);
```

However, when writing pixel data into the allocated surface, `_cairo_image_surface_create_from_jpeg()` iterates over the original dimensions specified by the JPEG, `srcinfo.output_width` and `srcinfo.output_height`, instead of the appropriate `destination_width` and `destination_height`. The nested loop structure below occurs in five locations of `cairo-image-surface-jpeg.c` that each handle a different type of color space.<sup>3</sup> <sup>4</sup> <sup>5</sup> <sup>6</sup> <sup>7</sup>

```c
while (srcinfo.output_scanline < srcinfo.output_height) {
	// ...
	for (x = 0; x < srcinfo.output_width; x++) {					
		// ...
		memcpy (p_surface, &pixel, sizeof (guint32));
```

Because the original JPEG dimensions may be larger than the memory area designated for the surface, this inconsistency can lead to attacker-controlled pixel data being written past the bounds of the `data` buffer of the `cairo_surface_t` structure.

## Proof of Concept
See the minimized test case, `poc.min.jpg`. This file is 107 bytes and specifies dimensions of 1 x 33000.

## AddressSanitizer Output (gThumb 3.8.2)
```
$ 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
```

## References
<sup>1</sup> <https://github.com/GNOME/gthumb/blob/0c0f0300d54d050ca87d23de4c734c24f37e8958/gthumb/cairo-utils.h#L32>

<sup>2</sup> <https://github.com/GNOME/gthumb/blob/0c0f0300d54d050ca87d23de4c734c24f37e8958/extensions/cairo_io/cairo-image-surface-jpeg.c#L266>

<sup>3</sup> <https://github.com/GNOME/gthumb/blob/0c0f0300d54d050ca87d23de4c734c24f37e8958/extensions/cairo_io/cairo-image-surface-jpeg.c#L307>

<sup>4</sup> <https://github.com/GNOME/gthumb/blob/0c0f0300d54d050ca87d23de4c734c24f37e8958/extensions/cairo_io/cairo-image-surface-jpeg.c#L355>

<sup>5</sup> <https://github.com/GNOME/gthumb/blob/0c0f0300d54d050ca87d23de4c734c24f37e8958/extensions/cairo_io/cairo-image-surface-jpeg.c#L387>

<sup>6</sup> <https://github.com/GNOME/gthumb/blob/0c0f0300d54d050ca87d23de4c734c24f37e8958/extensions/cairo_io/cairo-image-surface-jpeg.c#L434>

<sup>7</sup> <https://github.com/GNOME/gthumb/blob/0c0f0300d54d050ca87d23de4c734c24f37e8958/extensions/cairo_io/cairo-image-surface-jpeg.c#L489>
File Snapshot

Log in to view the POC file snapshot cached by Shenlong Bot

Log in to view
Remarks
    1. It is advised to access via the original source first.
    2. Local POC snapshots are reserved for subscribers — if the original source is unavailable, the local mirror is part of the paid plan.
    3. Mirroring, verifying, and maintaining this POC archive takes ongoing effort, so local snapshots are a paid feature. Your subscription keeps the archive online — thank you for the support. View subscription plans →