GNOME Bugzilla – Bug 752297
heap overflow and DoS affecting Firefox and other programs (x86_64)
Last modified: 2015-08-17 18:48:36 UTC
From: Gustavo Grieco <gustavo.grieco@imag.fr>, To: security@gnome.org Hello! We found a heap overflow and a DoS in the gdk-pixbuf implementation triggered by the scaling of a malformed bmp. These issues are affecting x86_64 builds (we tested in a fully updated Ubuntu 14.04 and Debian Wheezy). For example, Ubuntu 14.04 ships with gdk-pixbuf 2.30 but newer versions are affected as well. The issue happens when a program is trying to parse and scale a crafted bmp using gdk-pixbuf (for instance, using get_scaled_pixbuf). It will result at least in an DoS aborting the program with a SIGTRAP. It is also possible to perform a heap overflow if you select the suitable width and height in a malicious bmp according to the scaled width and height. The cause of the heap overflow is this integer overflow located here: https://github.com/GNOME/gdk-pixbuf/blob/f79085cbec9997895e252dce994d18139d719e26/gdk-pixbuf/pixops/pixops.c#L1275 and the insufficient checks performed in the gdk_pixbuf_new function. Interestingly enough, in a recent version of gdk-pixbuf (2.31 or newer) somebody replaced some old code that checks for a overflow with a g_try_malloc_n that is supposed to check for overflow, but it doesn't in x86_64 (you can see the old and new code here: https://github.com/GNOME/gdk-pixbuf/commit/deb78d971c4bcb9e3ccbb71e7925bc6baa707188#diff-cde3af8b5b1c0789407148d53a75 ae22R448) Unfortunately, at least Firefox and Chromium are using gdk-pixbuf primitives to implement file pickers, so they are affected. A minimal example of a vulnerable program is attached: it is just a call to gdk_pixbuf_new_from_file_at_size. Also two bmp POC are included: one to crash the minimal example and another POC to trigger a heap overflow in Firefox (it works with pixbuf 2.31 or newer). You should attach the uncompressed bmp or try to open it (using ctrl+O) (that's the reason we are sending it compressed!). Remember that this vulnerability depends on a malloc call and can fail if your real/virtual memory is not large enough. In particular, the Firefox POC requires at least 12GB of memory available for allocation. Regards, Gus.
Created attachment 307318 [details] overflow-firefox.bmp
Created attachment 307319 [details] pixbuf_vuln_poc.c
Created attachment 307320 [details] overflow-32x32.bmp
Not sure I see what x86_64 has to do with it - g_malloc_n works just fine here to detect overflow on x86_64. I do see the possibility for overflow in the g_new call you're pointing out, though. The attached patch tries to catch that possibility.
Created attachment 307326 [details] [review] pixops: Be more careful about integer overflow Our loader code is supposed to handle out-of-memory and overflow situations gracefully, reporting errors instead of aborting. But if you load an image at a specific size, we also execute our scaling code, which was not careful enough about overflow in some places. This commit makes the scaling code silently return if it fails to allocate filter tables.
Review of attachment 307326 [details] [review]: ::: gdk-pixbuf/pixops/pixops.c @@ +1278,3 @@ + n_weights = SUBSAMPLE * SUBSAMPLE * n_x * n_y; + if (n_weights / (SUBSAMPLE * SUBSAMPLE) != n_x * n_y) + return NULL; /* overflow, bail */ This can still overflow if n_x * n_y >= MAXINT. > if (n_weights / (SUBSAMPLE * SUBSAMPLE * n_x) != n_y) should be the right check.
Bug 752297 - heap overflow and DoS affecting Firefox and other programs (x86_64) - NEW Attachment 307326 [details] pushed as ffec86e - pixops: Be more careful about integer overflow
Pushed an update for this bug: commit 8dba67cb4f38d62a47757741ad41e3f245b4a32a Author: Benjamin Otte <otte@redhat.com> Date: Mon Aug 17 18:52:47 2015 +0200 pixops: Fix oversight for CVE-2015-4491 The n_x variable could be made large enough to overflow, too. Also included are various testcases for this vulnerability: - The original exploit (adapted for the testsuite) - Causing overflow by making both X and Y variables large - Causing overflow using only the X variable - Causing overflow using only the Y variable