Bug 1197059 (CVE-2015-7216)

Firefox in Linux is using Jasper which is unmaintained and vulnerable

VERIFIED FIXED in Firefox 43

Status

()

defect
VERIFIED FIXED
4 years ago
2 years ago

People

(Reporter: gustavo.grieco, Assigned: acomminos)

Tracking

({sec-moderate})

unspecified
mozilla43
Unspecified
Linux
Points:
---
Dependency tree / graph

Firefox Tracking Flags

(firefox43 verified, firefox-esr38 affected)

Details

(Whiteboard: [adv-main43+])

Attachments

(2 attachments, 2 obsolete attachments)

Posted file test.jp2.gz
User Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:39.0) Gecko/20100101 Firefox/39.0
Build ID: 20150629114848

Steps to reproduce:

In order to preview a jpeg image, Firefox is using gdk-pixbuf in Linux. Such library is loading this type of images using jasper (http://www.ece.uvic.ca/~frodo/jasper/). Unfortunately, this library is unmaintained and day after day we *easily* found new vulnerabilities. For instance:

* http://seclists.org/oss-sec/2015/q3/408
* http://seclists.org/oss-sec/2015/q3/366
* http://seclists.org/bugtraq/2015/Jan/101
* http://seclists.org/bugtraq/2014/Dec/133

You can find a list containing older vulnerabilities here:

http://www.cvedetails.com/vulnerability-search.php?f=1&vendor=&product=jasper&cveid=&cweid=&cvssscoremin=&cvssscoremax=&psy=&psm=&pey=&pem=&usy=&usm=&uey=&uem=

More recently,  I started fuzzing regression tests and i found even more issues, some of then affecting directly Firefox like a malformed image which can crash it. 
The attached files is one of the new issues (re)discovered and it will be reported soon (and more is about to come!). To reproduce it:

1. Download this attached compressed image somewhere
2. Uncompress it
3. Try to attach it or open it with Firefox.


Actual results:

Firefox executed buggy code from libjasper, which crashed. A complete stack trace is here:

#0  0x00007fffb9a32ebc in ?? () from /usr/lib/x86_64-linux-gnu/libjasper.so.1
#1  0x00007fffb9a3316e in ?? () from /usr/lib/x86_64-linux-gnu/libjasper.so.1
#2  0x00007fffb9a327fd in jpc_decode () from /usr/lib/x86_64-linux-gnu/libjasper.so.1
#3  0x00007fffb9a20ecd in jas_image_decode () from /usr/lib/x86_64-linux-gnu/libjasper.so.1
#4  0x00007fffb9c6bfad in jasper_image_try_load (error=<optimized out>, context=<optimized out>) at io-jasper.c:100
#5  jasper_image_stop_load (data=0x7fffc98eed80, error=0x7fffffff9bd0) at io-jasper.c:246
#6  0x00007fffedf4f3b8 in gdk_pixbuf_loader_close (loader=0x7fffbedf9c80, error=0x0) at gdk-pixbuf-loader.c:819
#7  0x00007fffedf4d436 in gdk_pixbuf_get_file_info (filename=<optimized out>, width=0x7fffffffac68, height=0x7fffffffac6c) at gdk-pixbuf-io.c:1948
#8  0x00007ffff2652b9b in ?? () from /usr/lib/firefox/libxul.so
#9  0x00007fffef50b3b8 in g_closure_invoke () from /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0
#10 0x00007fffef51cd3d in ?? () from /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0
#11 0x00007fffef524a29 in g_signal_emit_valist () from /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0
#12 0x00007fffef525212 in g_signal_emit_by_name () from /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0
#13 0x00007fffef50b3b8 in g_closure_invoke () from /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0
#14 0x00007fffef51cd3d in ?? () from /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0
#15 0x00007fffef524a29 in g_signal_emit_valist () from /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0
#16 0x00007fffef525212 in g_signal_emit_by_name () from /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0
#17 0x00007fffef50b3b8 in g_closure_invoke () from /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0
#18 0x00007fffef51cd3d in ?? () from /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0
#19 0x00007fffef524a29 in g_signal_emit_valist () from /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0
#20 0x00007fffef525212 in g_signal_emit_by_name () from /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0
#21 0x00007fffeec8d0e7 in ?? () from /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0
#22 0x00007fffeec903f0 in ?? () from /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0
#23 0x00007fffef50b5e7 in ?? () from /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0
#24 0x00007fffef524088 in g_signal_emit_valist () from /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0
#25 0x00007fffef524ce2 in g_signal_emit () from /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0
#26 0x00007fffeedd82be in ?? () from /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0
#27 0x00007fffeeddc868 in ?? () from /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0
#28 0x00007fffeece4815 in ?? () from /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0
#29 0x00007fffef50b3b8 in g_closure_invoke () from /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0
#30 0x00007fffef51cafb in ?? () from /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0
#31 0x00007fffef5246f9 in g_signal_emit_valist () from /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0
#32 0x00007fffef524ce2 in g_signal_emit () from /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0
#33 0x00007fffeedf4684 in ?? () from /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0
#34 0x00007fffeece2fc4 in gtk_propagate_event () from /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0
#35 0x00007fffeece337b in gtk_main_do_event () from /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0
#36 0x00007fffee3c91ec in ?? () from /usr/lib/x86_64-linux-gnu/libgdk-x11-2.0.so.0
#37 0x00007fffef23be04 in g_main_context_dispatch () from /lib/x86_64-linux-gnu/libglib-2.0.so.0
---Type <return> to continue, or q <return> to quit---
#38 0x00007fffef23c048 in ?? () from /lib/x86_64-linux-gnu/libglib-2.0.so.0
#39 0x00007fffef23c0ec in g_main_context_iteration () from /lib/x86_64-linux-gnu/libglib-2.0.so.0
#40 0x00007ffff265294c in ?? () from /usr/lib/firefox/libxul.so
#41 0x00007ffff2635b45 in ?? () from /usr/lib/firefox/libxul.so
#42 0x00007ffff2635c74 in ?? () from /usr/lib/firefox/libxul.so
#43 0x00007ffff1706f8d in ?? () from /usr/lib/firefox/libxul.so
#44 0x00007ffff17187ce in ?? () from /usr/lib/firefox/libxul.so
#45 0x00007ffff18c690d in ?? () from /usr/lib/firefox/libxul.so
#46 0x00007ffff18b7515 in ?? () from /usr/lib/firefox/libxul.so
#47 0x00007ffff262e2b1 in ?? () from /usr/lib/firefox/libxul.so
#48 0x00007ffff2b3a3c7 in ?? () from /usr/lib/firefox/libxul.so
#49 0x00007ffff2b6b8ec in ?? () from /usr/lib/firefox/libxul.so
#50 0x00007ffff2b6bbdd in ?? () from /usr/lib/firefox/libxul.so
#51 0x00007ffff2b6be68 in XRE_main () from /usr/lib/firefox/libxul.so
#52 0x0000555555558451 in _start ()

and the faulty instruction is examined here:

(gdb) x/i $rip
=> 0x7fffb9a32ebc:	mov    0x8(%r14),%rax
(gdb) info register
rax            0x7fffbed04cc0	140736394710208
rbx            0x7fffbd700068	140736371621992
rcx            0xffd9	65497
rdx            0x7fffb9c61c68	140736310156392
rsi            0x5a5a5a5a	1515870810
rdi            0x3	3
rbp            0x2	0x2
rsp            0x7fffffff9a50	0x7fffffff9a50
r8             0xffd9	65497
r9             0x7fffbed87000	140736395243520
r10            0x7ffff6c000c8	140737333166280
r11            0x7ffff6c00680	140737333167744
r12            0x7fffbed04a80	140736394709632
r13            0x7fffbed04ae8	140736394709736
r14            0x0	0
r15            0x7fffffffae60	140737488334432
rip            0x7fffb9a32ebc	0x7fffb9a32ebc
eflags         0x10206	[ PF IF RF ]
cs             0x33	51
ss             0x2b	43
ds             0x0	0
es             0x0	0
fs             0x0	0
gs             0x0	0


For this concrete example, it was just a null dereference and more than a DoS is unlikely to happen but next time we could find a worse case.


Expected results:

I think we should disable image preview for jpeg until gdk-pixbuf change Jasper for a more modern implementation of jpeg decoding (e.g, openjpeg)
I'm not sure we can avoid this... for some functions we rely on the OS, and this is what the OS is picking.
Group: firefox-core-security → core-security
Status: UNCONFIRMED → NEW
Ever confirmed: true
Flags: needinfo?(benjamin)
Product: Firefox → Core
Version: 39 Branch → unspecified
Hello!, 

A little update on the crashing example: it looks like some uninitialized values are used to compute something in libjasper. This looks difficult to exploit, but in theory possible, since the attacker controls every byte of the file, causing a deallocation to contain some stuff that can end in the same offset of this null pointer.

Also, i can provide more examples of jpeg causing aborts/sigpe (no security risk, afaik), but i think that the main point is the existence of easy to discover vulnerabilities in Jasper.
302 sfowler as imagelib maintainer.
Flags: needinfo?(benjamin)
Flags: needinfo?(seth)
I doubt we're relying on the OS library for browser-related image preview. My guess is that the bug is about the file chooser (File->Open). There's nothing that can be done in imagelib about that.

Gustavo, can you confirm, this is what you're talking about?
Note that if we _are_ talking about the file chooser, there's an alternative to disabling previews:
https://developer.gnome.org/pygtk/stable/class-gtkfilechooser.html#AddingAPreviewWidget
(In reply to Mike Hommey [:glandium] from comment #4)
> I doubt we're relying on the OS library for browser-related image preview.
> My guess is that the bug is about the file chooser (File->Open). There's
> nothing that can be done in imagelib about that.
> 
> Gustavo, can you confirm, this is what you're talking about?

Exactly. The file chooser is using gdk-pixbuf which is using jasper to load jpeg files. Interestingly enough, this also affect chromium, since they have a very similar code for the file chooser in Linux. I also notified them but they marked as WONTFIX saying: "we will wait the upstream fix" (despite nobody is supporting Jasper).

Also, i'm not sure if i should disclose it to oss-security as the redhat security team ask me to (somebody can create a patch if it is public, but it will be also available for bad guys to start actively looking for exploits affecting Firefox). What should i do?
OS: Unspecified → Linux
To be honest I know nothing about the file chooser or its integration with the OS. This is actually not a function which is handled by ImageLib.

Andrew, I'm not sure whether you're the right person to look at this, but you seem to have written some of the code in |widget/gtk/nsFilePicker.cpp| and therefore I'm guessing you might know who would be.
Flags: needinfo?(seth) → needinfo?(acomminos)
(In reply to Seth Fowler [:seth] [:s2h] from comment #7)
> Andrew, I'm not sure whether you're the right person to look at this, but
> you seem to have written some of the code in |widget/gtk/nsFilePicker.cpp|
> and therefore I'm guessing you might know who would be.

As Gustavo said, the issue stems from the usage of GDK-PixBuf to provide a GtkImage with bitmap data (GtkImage didn't support cairo surfaces until 3.10). We do, however, make calls into GDK-PixBuf that we *can* avoid; this stack appears to stem from the following call in widget/gtk/nsFilePicker.cpp:

> GdkPixbufFormat *preview_format = gdk_pixbuf_get_file_info(image_filename,
>                                                            &preview_width,
>                                                            &preview_height);


I think we could work around this quite nicely by decoding the file with imagelib and then wrapping it in a GdkPixbuf backed by RGB data using gdk_pixbuf_new_from_data. That way, jasper never gets called to decode the preview image file.

https://developer.gnome.org/gdk-pixbuf/unstable/gdk-pixbuf-Image-Data-in-Memory.html
Flags: needinfo?(acomminos)
We could also disable the jasper module at runtime using gdk_pixbuf_format_set_disabled (https://developer.gnome.org/gdk-pixbuf/unstable/gdk-pixbuf-Module-Interface.html#gdk-pixbuf-format-set-disabled), killing support for JPEG 2000 files in previews.
Here's a possible solution that outright disables JPEG2000 support in GDK-PixBuf (which depends on the JasPer decoder). As we don't use GDK-PixBuf for very much, I think this is a reasonable workaround.
Attachment #8653253 - Flags: review?(karlt)
Removed unnecessary printf.
Attachment #8653253 - Attachment is obsolete: true
Attachment #8653253 - Flags: review?(karlt)
Attachment #8653254 - Flags: review?(karlt)
Assignee: nobody → acomminos
Status: NEW → ASSIGNED
Attachment #8653254 - Flags: review?(karlt) → review+
Comment on attachment 8653254 [details] [diff] [review]
Disable JasPer support in GDK-PixBuf.

[Security approval request comment]
> How easily could an exploit be constructed based on the patch?

Quite easily, as demonstrated by the reporter.

> Do comments in the patch, the check-in comment, or tests included in the patch paint a bulls-eye on the security problem?

No, they just mention that we disable JasPer.

> Which older supported branches are affected by this flaw?

All supported branches are affected on Linux/GTK.

> Do you have backports for the affected branches? If not, how different, hard to create, and risky will they be?

This should apply quite cleanly to all supported branches (fairly standalone).

> How likely is this patch to cause regressions; how much testing does it need?

Unlikely to need testing. The only regression is the obvious one of killing JPEG2000 support in file picker previews.
Attachment #8653254 - Flags: sec-approval?
Calling this a sec-moderate. This doesn't need sec-approval as such so I'll clear that. Check it in.
Keywords: sec-moderate
Attachment #8653254 - Flags: sec-approval?
So apparently, gdk_pixbuf_format_get_name() has chosen to use g_strdup() even though the docs don't indicate.  gtkselection.c passes the pointer to g_free() so we should be safe to do the same.
Weird. Thanks for letting me know, updated to fix the leak with g_free.

https://treeherder.mozilla.org/#/jobs?repo=try&revision=34925c1100fd
Attachment #8653254 - Attachment is obsolete: true
Attachment #8654344 - Flags: review+
https://hg.mozilla.org/mozilla-central/rev/9a074478c2d3
Status: ASSIGNED → RESOLVED
Closed: 4 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla43
Group: core-security → core-security-release
Whiteboard: [adv-main43+]
Reproduced the initial issue on Ubuntu 14.04 64 bit using an old Asan Nightly build from 2015-08-20, verified that the issue does not reproduce anymore using Firefox 43 beta 9, latest Asan Developer Edition 44.0a2, latest Asan Nightly 45.0a1 and Firefox 38.4.0esrpre (buildID: 20151208033922).
Status: RESOLVED → VERIFIED
Alias: CVE-2015-7216
Group: core-security-release
Moving from Core::Untriaged to Core::General https://bugzilla.mozilla.org/show_bug.cgi?id=1407598
Component: Untriaged → General
You need to log in before you can comment on or make changes to this bug.