After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 784903 - (CVE-2017-2870) CVE-2017-2870 Gdk-Pixbuf TIFF tiff_image_parse Code Execution Vunerability (integer overflow)
(CVE-2017-2870)
CVE-2017-2870 Gdk-Pixbuf TIFF tiff_image_parse Code Execution Vunerability (i...
Status: RESOLVED DUPLICATE of bug 780269
Product: gdk-pixbuf
Classification: Platform
Component: loaders
unspecified
Other Linux
: Normal normal
: ---
Assigned To: gdk-pixbuf-maint
gdk-pixbuf-maint
Depends on:
Blocks:
 
 
Reported: 2017-07-13 13:12 UTC by Tobias Mueller
Modified: 2017-08-25 18:53 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
crashing file, password "crash" (266 bytes, image/tiff)
2017-07-13 14:14 UTC, Tobias Mueller
Details

Description Tobias Mueller 2017-07-13 13:12:21 UTC
We receive a report on security@.
Comment 1 Tobias Mueller 2017-07-13 13:15:18 UTC
### Summary
An exploitable integer overflow vulnerability exists in the tiff_image_parse functionality of Gdk-Pixbuf 2.36.6 when compiled with Clang. 
A specially crafted tiff file can cause a heap-overflow resulting in remote code execution. An attacker can send a file or a URL to trigger this vulnerability. 


### Tested Versions

Gdk-Pixbuf 2.36.6 commit: aba8d88798dfc2f3856ea0ddda14b06174bbb2bc
compiled with clang -O3 flag
libtiff 4.0.6

### Product URLs
[https://developer.gnome.org/gdk-pixbuf/](https://developer.gnome.org/gdk-pixbuf/)


### CVSSv3 Score

8.8 - CVSS:3.0/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H

### CWE
CWE-758: Reliance on Undefined, Unspecified, or Implementation-Defined Behavior

### Details
	Gdk-Pixbuf is a toolkit for image loading and pixel buffer manipulation used in various type of desktop applications: image viewers(GNOME thumbnailer), web browsers (Chromium, Firefox), media players (VLC), etc.
The vulnerability exists in the TIFF parser and only manifests itself when the library is compiled with high optimization flags `-O3` (tested with Clang, gcc does not remove the check). Several defined `if statements` 
inside the `tiff_image_parse` function  are responsible of integer overflow checks or at least that was their intention. Because the checks are made on signed integers, the condition cannot evaluate to false unless an 
integer overflow occurs.  According to the C standard, a signed integer overflow is defined as "Undefined Bahavior", thus behaviour related to it is implementation dependent and in the case of Clang the check is removed.
Finally the lack of proper integer overflows check leads to heap overflow and can allow attackers to obtain arbitrary code execution.

The code below is removed from compilation process because it would be true if a `signed integer overflow` would occur which is `undefined bahavior`:

	Line 89         gint width, height, rowstride, bytes;
	Line 128        rowstride = width * 4;
	Line 129        if (rowstride / 4 != width) { /* overflow */
	Line 130                g_set_error_literal (error,
	Line 131                                     GDK_PIXBUF_ERROR,
	Line 132                                     GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
	Line 133                                     _("Dimensions of TIFF image too large"));
	Line 134                return NULL;                
	Line 135        }
	Line 136        
	Line 137        bytes = height * rowstride;
	Line 138        if (bytes / rowstride != height) { /* overflow */
	Line 139                g_set_error_literal (error,
	Line 140                                     GDK_PIXBUF_ERROR,
	Line 141                                     GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
	Line 142                                     _("Dimensions of TIFF image too large"));
	Line 143                return NULL;                
	Line 144        }


in our case the variables have the following values:

	width  = 0x8020
	height = 0xfff7
	
which causes an integer overflow at `line 137`:
	
	bytes = height * ( width * 4)
    
Then, based on the overflowed value, a buffer is allocated :

	Line 160       pixels = g_try_malloc (bytes);
	
Then all three parameters: width,height and the allocated `bytes` buffer are passed as arguments:

	Line 272		if (!TIFFReadRGBAImageOriented (tiff, width, height, (uint32 *)pixels, ORIENTATION_TOPLEFT, 1)) {	
	
Because buffer `bytes` was allocated based on overflowed value, width and height parameters mismatch the size of the buffer which leads to out of bound writes (Line 1362) inside the `put1bitbwtile` function while reading RGB values:


	libtiff/tif_getimage.c:1326
	Line 1351	/*
	Line 1352	 * 1-bit bilevel => colormap/RGB
	Line 1353	 */
	Line 1354	DECLAREContigPutFunc(put1bitbwtile)
	Line 1355	{
	Line 1356		uint32** BWmap = img->BWmap;
	Line 1357
	Line 1358		(void) x; (void) y;
	Line 1359		fromskew /= 8;
	Line 1360		while (h-- > 0) {
	Line 1361		uint32* bw;
	Line 1362		UNROLL8(w, bw = BWmap[*pp++], *cp++ = *bw++);
	Line 1363		cp += toskew;
	Line 1364		pp += fromskew;
	Line 1365		}
	Line 1366	}	

	
### Crash Information 

	valgrind ./pixbuf-read crashes/tiff_bug.tiff
	==32378== Invalid write of size 4
	==32378==    at 0x4B5D71D: put1bitbwtile (tif_getimage.c:1326)
	==32378==    by 0x4B5BE5E: gtTileContig (tif_getimage.c:673)
	==32378==    by 0x4B5B810: TIFFRGBAImageGet (tif_getimage.c:495)
	==32378==    by 0x4B5B8ED: TIFFReadRGBAImageOriented (tif_getimage.c:514)
	==32378==    by 0x4067A59: tiff_image_parse (io-tiff.c:272)
	==32378==    by 0x406634C: gdk_pixbuf__tiff_image_stop_load (io-tiff.c:477)
	==32378==    by 0x4048442: gdk_pixbuf_loader_close (gdk-pixbuf-loader.c:822)
	==32378==    by 0x8048903: test_loader (pixbuf-read.c:35)
	==32378==    by 0x8048903: main (pixbuf-read.c:75)
	==32378==  Address 0x5343ba8 is 0 bytes after a block of size 7,207,808 alloc'd
	==32378==    at 0x402D17C: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
	==32378==    by 0x432C3BF: g_try_malloc (in /lib/i386-linux-gnu/libglib-2.0.so.0.4800.2)
	==32378==    by 0x4067584: tiff_image_parse (io-tiff.c:160)
	==32378==    by 0x406634C: gdk_pixbuf__tiff_image_stop_load (io-tiff.c:477)
	==32378==    by 0x4048442: gdk_pixbuf_loader_close (gdk-pixbuf-loader.c:822)
	==32378==    by 0x8048903: test_loader (pixbuf-read.c:35)
	==32378==    by 0x8048903: main (pixbuf-read.c:75)

### Credit 

Discovered by Marcin 'Icewall' Noga of Cisco Talos.
Comment 2 Tobias Mueller 2017-07-13 13:27:08 UTC
I believe this is bug 780269.
The patch (attachment 348263 [details] [review]) changes the preconditions of exactly the two multiplications mentioned here in this bug report.

Feel free to unmark as duplicate if my analysis is wrong.

*** This bug has been marked as a duplicate of bug 780269 ***
Comment 3 Bastien Nocera 2017-07-13 14:03:15 UTC
Where's the reproducer for this one?
Comment 4 Tobias Mueller 2017-07-13 14:14:20 UTC
Created attachment 355516 [details]
crashing file, password "crash"
Comment 5 Bastien Nocera 2017-07-13 15:05:13 UTC
This works as expected when compiled with GCC, like 99% of Linux distributions. I'll add the test case to git now.
Comment 6 Bastien Nocera 2017-07-13 15:09:57 UTC
commit 3b8559efaa0907c8b9a1ae5e6db7f62cca331c62
Author: Bastien Nocera <hadess@hadess.net>
Date:   Thu Jul 13 17:06:12 2017 +0200

    tests: Add a test image for extra large dimensions in TIFF loader
    
    Overflow checks were added in commit 14904cb842.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=784903
Comment 7 Tobias Mueller 2017-07-13 15:21:13 UTC
(In reply to Bastien Nocera from comment #5)
> This works as expected when compiled with GCC, like 99% of Linux
> distributions. I'll add the test case to git now.

yeah, it's undefined behaviour. Compilers can do what they want. GCC may be fine in this very case. Although it's clear that they regard these types of overflow check as wrong as this bug report shows: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=30475#c10

So the checks introduced in commit 14904cb842 are not good according to GCC people.  It's undefined behaviour after all.  Checks that do not rely on undefined behaviour are proposed in bug 780269.

A similar issue is in bug 776694, I think.
Comment 8 Bastien Nocera 2017-07-13 16:02:32 UTC
(In reply to Tobias Mueller from comment #7)
> (In reply to Bastien Nocera from comment #5)
> > This works as expected when compiled with GCC, like 99% of Linux
> > distributions. I'll add the test case to git now.
> 
> yeah, it's undefined behaviour. Compilers can do what they want. GCC may be
> fine in this very case. Although it's clear that they regard these types of
> overflow check as wrong as this bug report shows:
> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=30475#c10
> 
> So the checks introduced in commit 14904cb842 are not good according to GCC
> people.  It's undefined behaviour after all.  Checks that do not rely on
> undefined behaviour are proposed in bug 780269.

Fair enough, but that bug report is still 5 years younger than the commit for add those overflow checks. "Wrong" is also relative. It's undefined, but seems to have worked in a defined way for at least 15 years ;)

> A similar issue is in bug 776694, I think.

I'll look as well.
Comment 9 Bastien Nocera 2017-08-25 18:53:53 UTC
Duplicate of a public bug, making public.