Tuesday, November 15, 2016

[0day] [PoC] Risky design decisions in Google Chrome and Fedora desktop enable drive-by downloads

A confluence of two risky design choices, combined with various implementation issues, makes drive-by downloads possible with Google Chrome on Fedora. In total, with the risky design choices first, the issues are:

  • Chrome will auto download files to a user’s desktop with no confirmation.
  • Fedora’s “tracker” software will auto crawl downloaded files to index them, including media files.
  • The “gstreamer” framework, as used to handle media in the Fedora desktop, has questionable implementation quality from a security perspective.
  • The “tracker” component responsible for parsing media files does not appear to be sandboxed (e.g. with SELinux).
  • The Fedora default desktop install includes a range of fairly obscure media decoders that confer risk but are not necessary for a thorough desktop experience.

Demonstration and proof of concept
In the screenshot below, the user of the Chrome browser has visited a (malicious) website and you can see the result is a forced download leading to the side effect of a crash in a process unrelated to the web browser:


“We’re sorry, it looks like the Tracker Metadata Extractor crashed.” It certainly did, without the user needed to do anything other that visit a web page. It is not necessary to click on the button corresponding to the download.

This is in a default install of Fedora 24, but with the gstreamer updates applied (without them, gstreamer doesn’t work correctly). The crashing binary is /usr/libexec/tracker-extract. It has ASLR enabled, which is good. But ps -eZ identifies the security context as unconfined_u:unconfined_r:unconfined_t, which appears unsandboxed. The crash manifests as an out-of-bounds write.

The demo file can be downloaded here: vmnc_width_height_int_oflow.avi.

This vulnerability also affects the default install of Ubuntu 16.04, as long as the “mp3” option was selected during install. (This vulnerability appears to go significantly back into history, at least affecting all the way back to Ubuntu 12.04 and it’s older gstreamer-0.10.) Ubuntu doesn’t seem to index desktop files by default though, so the impact on Ubuntu will be less severe but still nasty via e.g. triggering thumbnailing by opening the nautilus file browser in the Downloads directory. Or opening a USB drive. Or e-mailing someone the exploit file and have them open it in a media player.

0day details
(Absent a CVE, you can uniquely identify this as CESA-2016-0002.)
The vmnc decoder renders video for a VMware screen capture format. This format is usually contained within an AVI container. The vmnc decoder in the gstreamer code base contains a fairly obvious and simple width * height * depth integer overflow in the allocation of the render buffer. From gst-plugins-bad1.0/gst/vmnc/vmncdec.c:

static int
vmnc_handle_wmvi_rectangle (GstVMncDec * dec, struct RfbRectangle *rect,
   const guint8 * data, int len, gboolean decode)
 bpp = data[0];
 dec->format.bytes_per_pixel = bpp / 8;
 dec->format.width = rect->width;
 dec->format.height = rect->height;
 dec->imagedata = g_malloc (dec->format.width * dec->format.height *

In the above code, rect->width and rect->height are attacker controlled 16-bit unsigned values taken straight from the input file. bpp is also taken from the input file, and is validated to be one of the typical depth values 8, 16, 32.

To create the PoC, an existing sample file was located from the excellent MPlayerHQ test set: test.avi. This is a vmnc-inside-avi sample file. All that is changed in the PoC is that the width and height values at file offset 0x201c are changed to 65535 and 32769, respectively. The base image is a 16bpp image, so the calculation on the overflow line is 65535 * 32769 * 2. In signed 32-bit integer math, the result is 65534. That’s a reasonable sized buffer but subsequent decoding believes that it has a huge 65535 x 32769 canvas to render into. Heap based buffer overflow results.

To be a bit more specific, there are a couple of challenges which would make this exploit tricky: firstly, this is 64-bit modern Linux (and in particular, Fedora), where the ASLR is generally pretty good. Secondly, the attacker does not have the luxury of attacking this vulnerability from a scripting environment. This is key, and makes things much harder, because pointers cannot be readily calculated based on information leaks, decisions cannot be made based on measurements of corruption side effects, etc.

However, on the flipside, there are a lot of ways in which the attacker has a lot of control and assistance to exploit this, even without script to help. Let’s enumerate them, we might find the range of possibilities surprising:

  • Precise control over heap chunk size that is overflowed. By fiddling with the width, height and bpp values that factor into the integer overflow, we can choose a wide range of different chunk sizes to later go off the end of. This means we can corrupt a lot of different areas of the heap depending on what works best.
  • Surprisingly stable heap layout. The vmnc decoding kicks off on a relatively fresh thread, which typically has a relatively fresh glibc per-thread malloc arena. Heap grooming may only be minimally required, if at all.
  • Possibility for 3 byte partial pointer overwrites. Because the overflow is kicking off inside a glibc thread area, the alignment of the arena is typically to 16MB or so. This means you can potentially do up to a 3 byte partial pointer overwrite reliably. In the world of partial pointer overwrites, this is a luxury.
  • Excellent heap grooming opportunities inside the vmnc decode loop. Inside the main decode loop, there are lots of opportunities to allocate and free memory, with great control over the sizes. This occurs in vmnc_handle_wmvi_rectangle(), which can reallocate the existing decode buffer, and vmnc_handle_wmvd_rectangle(), which allocates and frees cursor buffers. This level of control will allow good heap grooming, and the possibility of attacking heap metadata, if no other good opportunities present themselves.
  • A copy primitive as one of the rendering modes. This is super big. vmnc_handle_copy_rectangle() is a rendering mode that will take pixels from one area of the image and copy them to another area of the image. Since our integer overflow leads to a small image buffer but a huge image canvas size, you can see that this will enable us to read some out-of-bounds content and write that out-of-bounds. This solves one of the hardest problems we might face, which is to synthesize valid pointers in the presence of good ASLR. We can read an existing valid pointer that is out-of-bounds, and then copy it somewhere else, also out-of-bounds.

To back up a couple of the above points, we can briefly look at the PoC crashing in gdb. We’ll run the PoC through the totem media player on both Ubuntu 16.04 and Fedora 24:

gdb totem
r vmnc_width_height_int_oflow.avi
(gdb) bt
#0  __memcpy_avx_unaligned ()
(gdb) i r
rsi            0x7fffbb5e0015 140736336887829
rdi            0x7fffa40237fe 140735944996862

The last three bytes of the rdi register at the time of the crash are reasonably consistent across both Ubuntu and Fedora, at 0x0237fe. This is just off the end of a glibc thread arena, which ends at 0x022000. This illustrates the fairly clean heap state, and the 16MB+ alignment of thread arenas.

It’s clear that writing this exploit would be a lot of fun. I’ll put it on my TODO list, but I’d love to see someone else pick it up.

Google Chrome’s culpability
Let’s be clear: Google Chrome is the most secure of the common general purpose browsers out there. It has had more effort and money put into sandboxing, code quality, mitigations, fuzzing and community security involvement than the other browsers. This is all backed by a large, strong security team -- the largest monetary investment of the major browser vendors, which speaks volumes.

However, the default download behavior is one where you can point to e.g. Firefox’s solution as demonstrably superior: the user has to accept any random attacker supplied bytes before they are dumped to disk in a well known and indexable location, with an attacker supplied filename and extension.

This could be a default behavior to re-align with other browsers, to avoid known security headaches, and probably some as-yet-undiscovered ones too.

Absent action from the Chrome developers, there is fortunately a setting that can be used in environments where security is a concern: chrome://settings -> Show advanced settings -> Downloads -> Ask where to save each file before downloading.

Fedora’s culpability
You can clearly see the appeal of parsing and indexing all files that appear on disk. It enables desktop functionality that some users will consider userful. Certainly, other non-Linux operating systems do some of this too. But, this cannot be done carelessly. The lack of a robust sandbox for automatically parsing media formats seems like the largest gap Fedora has.

This is a problem that lends itself nearly ideally to sandboxing: the inputs and outputs and clear, and the rights needed to transform the inputs into the outputs are minimal. The input is just a memory chunk of the media file to be indexed. The output is a few metadata strings, perhaps some fixed format thumbnail canvases, etc. And the rights needed to do the transform are probably minimal: no writable filesystem access, no network access, no other process access, etc.

There’s also the concern that the media attack surfaces are a little out of hand. The default desktop install offers a range of fringe decoders that provide risk, for little benefit. In the case of Fedora 24, the faulty plug-in is pulled in via the default package gstreamer1-plugins-bad-free. From the gstreamer documentation: “these plug-ins are Bad with a capital B”. I’m not the first to notice this possible disconnect. From Ted Unangst’s post: “I do not want something called gstreamer-plugins-bad to be connected to the internet”. For some of the most dodgy decoders, we probably shouldn’t even be providing a nice automatic UI to offer to install them, because users will just click “yes”.

We can note that one quick way to break the link between the two risky designs is to remove the user/Downloads folder from the list of indexed paths. This can be achieved via the tracker-preferences tool, see below.

Disabling or removing tracker is non-trivial. This thing is like a virus! There’s some good information here: How do I disable tracker? To distill it:

  • There’s a non-default-install tool, tracker-preferences, that appears to offer the ability to disable indexing, or configure which paths are indexed.
  • Or you may prefer to just eviscerate tracker from your install. A lot of things depend on it, but rpm -e tracker --nodeps does not appear to blow things up too badly.
  • Beware that even after removing the tracker package, a log out and then in still left the daemons running for me. Perhaps do a reboot to be safe.

Bonus 0day
(Absent a CVE, you can uniquely identify this as CESA-2016-0003.)
The render canvas, as allocated in the code snippet quoted way above, is not black filled or otherwise initialized. The call to g_malloc() is just a thin wrapper around malloc(), which does not initialize any returned heap area. Therefore, there’s an easy information leak in thumbnailing a simple 1 frame vmnc movie that does not draw to the allocated render canvas at all. This could be a problem for anyone using gstreamer in a server environment to provide thumbnailing services.

Closing notes
Did I mention that ffmpeg has a vmnc decoder too and it appears more robust than the gstreamer one?

This was too easy. It should not be possible to find a serious memory corruption vulnerability in the default Linux desktop attack surface with just a few minutes of looking. Although it’s hard to say it, this is not the kind of situation that occurs with a latest Windows 10 default install. Is it possible that Linux desktop security has rotted?


Anonymous said...

Exposing security vluns as 0day exploits without allowing vendors to fix them beforehand is a very douchey move.

Anonymous said...

The same with google exposing other software companies vulnerabilities without giving them time to make a patch.

Hanno Böck said...

FYI, gstreamer upstream has fixed it:

Anonymous said...

Nautilus also crashes when the properties of the file are shown and possibly the thumbnailer is also affected.
Thanks for looking into this. The Linux desktop needs more scrutiny IMO.

Anonymous said...

> Although it’s hard to say it, this is not the kind of situation that occurs with a latest Windows 10 default install.

Saying this after the myriads of no-go bugs in Windows in the recent years makes me laugh.
Are Linux-based Desktop systems perfectly secure? Nope. Did Linux-based systems have their
share of security issues recently? Yep.

On top, saying that "Fedoras Gnome" is "Linux desktop security" is .. I leave that to you.

The icing is the irresponsible behaviour of not only saying that crap above, but also disclosing a 0day without talking to the developers. I expect better of a (albeit previous) part of Googles Project Zero.

Anonymous said...

Hanno Boeck's comment is the important one, here.
Look at the date of the fix!
Disclosure: 15.11.2016
Fix: 16.11.2016

No piece of software is truly impregnable, bugs happen, things are overlooked. The mayor difference then is the response time. That is what makes "Linux" more secure than Windows. It has been and will surely be this way for a long time.

Anonymous said...

I don't think releasing this 0day is bad style.
I don't expect any vendor to fix the real bug: indexing unknown files from anywhere.

Closing the specific codec vulnerability only helps until the next one is found, so the whole concept of indexing all files is broken.

Fedora has to fix the whole GNOME3 desktop bundeling in a way to remove single components like gstreamer1-plugins-bad without having 47 other packages remove including kernel-core.
Uninstalling tracker "only" removes nautilus, but I don't expect fedora too loosen the dependencies in their desktop.

Anonymous said...

Look at this, its a real hacK and not a crash:

Anonymous said...

Yes, Windows 10 is by far the best OS of this galaxy. The only reason people use Linux is to find some bugs, because they can be found and fixed - do that with the best OS of the galaxy!

Anonymous said...

Hey there, so Windows 10 out of the box is more secure as you mentioned -
"Although it’s hard to say it, this is not the kind of situation that occurs with a latest Windows 10 default install. Is it possible that Linux desktop security has rotted?"

But why did you compare it to not out of the box Fedora ? Fedora does not include Chrome browser or Chrome repo by default, so you actually downloaded 3rd party software that is not officially supported by Fedora and you thought that Linux have easy to find vulnerabilities -
" This was too easy. It should not be possible to find a serious memory corruption vulnerability in the default Linux desktop attack surface with just a few minutes of looking."

This is not so much a problem in Fedora or Linux is a problem in Chrome.

Unknown said...

Bugs like this are the primary reason why Tracker extracts metadata from files in a separate tracker-extract process. That process runs entirely in the background, and chances are very high that a crash won't affect a user-facing application. For example, Chrome didn't crash as a result of the tracker-extract crash.

For a user-facing application to crash, it has to run gstreamer's vmncdec in-process. That is why totem crashes if you try to run this file.

Forget Tracker. The way things stand today, someone can potentially exploit Firefox (and lot of other software) to steal your private keys, or spy on your using the laptop's camera. I believe the long term answer involves:

(a) Sandboxed Flatpak (http://flatpak.org/) applications. So that any random application on the computer can not perform any potentially suspicious activity behind the user's back.

(b) Portals that act as gatekeepers to such resources (like network, camera, files). I can imagine a 'import from web browser' portal that will explicitly let you select a file from the web that you want to expose to the rest of the desktop.

Jarth said...

(in)Security culture and corporate culture are taking hold of Linux and open source, that' why. They've already destroyed the open culture in the late nineties, are they at it again ?

Why else would systemd get pushed and accepted while it breaks so much of the Linux/Unix philosophy ? Exploitation vectors such as these are proof the open source model is only vaguely implemented when it comes to operational security.

On the other hand, what would the world look like if an impenetrable desktop would emerge ? Would anyone want that ?

Carlos Garnacho said...

Hello, Tracker maintainer here.

While it may be a valid point of debate whether indexing the Downloads folder by default or not, I think this post has *lots* of handwaving:
- First, you soon point to the problem being in a "Fedora choice", it's not. To trigger this specific bug you needed to install and run software from two different third party repositories (rpmfusion and google). Sorry, your warranty is void.
- Second, remember it's a *default*, users can configure this (or disable file indexing entirely) in the control center. If you think it's far fetched, it's just as much as it is installing software from third party repos.
- Third, this is not a 0day, there is no exploit. Furthermore, the GStreamer guys were extremely fast in fixing it. You could claim that other libraries used for metadata extraction are just as insecure, but that'd really be bugs in these libraries to fix. If a library is vulnerable then the exploit is latent anyway, be it Tracker, a thumbnailer, a previewer or a video player who stumbles on it. And anyway, until there's a real exploit that may trigger this way on a default Fedora install, I'll hear you crying wolf.

Going further, we could deem every file a potential exploit, and every running application a potential information leech. There's this flatpak sandboxing infrastructure which the GNOME desktop (and Tracker specifically) is committing to, if you had bothered contacting the affected upstreams you might know a proper solution is on the works.

Also, nice work agitating the zealots...