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 779016 - (CVE-2017-6313) Integer underflow in io-icns.c
(CVE-2017-6313)
Integer underflow in io-icns.c
Status: RESOLVED FIXED
Product: gdk-pixbuf
Classification: Platform
Component: loaders
git master
Other All
: Normal critical
: ---
Assigned To: gdk-pixbuf-maint
gdk-pixbuf-maint
Depends on:
Blocks:
 
 
Reported: 2017-02-21 13:04 UTC by Ariel Zelivansky
Modified: 2017-12-05 11:02 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
An icns file with icns to demonstrate infinite loop/out-of-bounds read (32 bytes, image/x-icns)
2017-02-21 13:04 UTC, Ariel Zelivansky
  Details
Example of segmentation fault (out-of-bounds read) with ico inside (518 bytes, image/x-icns)
2017-02-21 13:05 UTC, Ariel Zelivansky
  Details
icns: Protect against too short blocklen (CVE-2017-6313) (1007 bytes, patch)
2017-12-05 11:00 UTC, Bastien Nocera
committed Details | Review
tests: Add test for bug 779016 (760 bytes, patch)
2017-12-05 11:00 UTC, Bastien Nocera
committed Details | Review

Description Ariel Zelivansky 2017-02-21 13:04:11 UTC
Created attachment 346319 [details]
An icns file with icns to demonstrate infinite loop/out-of-bounds read

In the load_resources function (io-icns.c:63), inside the size switch (line 101), all the cases set plen or mlen to: blocklen - sizeof (IcnsBlockHeader);
See lines 109, 117, 127, 134, 139, 146, 151, 158 and 163.
blocklen is set in line 95:

blocklen = GUINT32_FROM_BE (header->size);

There are no checks on the size of blocklen and if it is set to less than sizeof (IcnsBlockHeader) (should be 8) there is an integer underflow.

This is dangerous because it's value is later passed to gdk_pixbuf_loader_write (line 262) when size is 256. This allows an attacker to craft a file that will end up calling to a desired loader with a bogus size that is much larger than the actual buffer size.

Possible exploits of the bug: 
1. adding a bmp, or a an ico image data after the header will cause an out-of-buffer read (again when count>actual buffer size). 
2. With a tiff image it would lead to an infinite loop
3. With a gif, a tga or another icns after the header the code will try to allocate as much as count bytes (and most likely fail on a size of 2^32-1)
4. With another icns it is possible to reach another out-of-bounds read that reads zeros and leads to an infinite loop

Certainly there may be more to that but that's what I found from a quick trial and error.

I tested this on Arch Linux and on Ubuntu 16.04.1 (both 32-bit and 64-bit versions).
Comment 1 Ariel Zelivansky 2017-02-21 13:05:37 UTC
Created attachment 346320 [details]
Example of segmentation fault (out-of-bounds read) with ico inside
Comment 2 Ariel Zelivansky 2017-02-21 14:00:37 UTC
Also perhaps postpone the call gdk_pixbuf_loader_write and first validate the file is actually JPEG 2000 if it is only used to reading JPEG 2000 images
Comment 3 Bastien Nocera 2017-12-05 11:00:40 UTC
Created attachment 365016 [details] [review]
icns: Protect against too short blocklen (CVE-2017-6313)

The blocklen needs to be at least header sized to be valid, otherwise we
can underflow picture data or mask data lengths.
Comment 4 Bastien Nocera 2017-12-05 11:00:46 UTC
Created attachment 365017 [details] [review]
tests: Add test for bug 779016
Comment 5 Bastien Nocera 2017-12-05 11:02:08 UTC
Attachment 365016 [details] pushed as 210b163 - icns: Protect against too short blocklen (CVE-2017-6313)
Attachment 365017 [details] pushed as 4cc39d4 - tests: Add test for bug 779016