Reliably compromising Ubuntu desktops by attacking the crash reporter

In this post I’ll describe how I found a remote code execution bug in Ubuntu Desktop which affects all default installations >= 12.10 (Quantal). The bug allows for reliable code injection when a user simply opens a malicious file. The following video demonstrates the exploit opening the Gnome calculator. The executed payload also replaces the exploit file with a decoy zip file to cover its tracks.

The full source code for this exploit is available on Github.

This research was inspired by Chris Evan’s great work on exploiting client-side file format parsing bugs in the gstreamer media library on Ubuntu. We will look for other default file handlers on Ubuntu which may be vulnerable to exploitation. I’m not a binary exploitation guru like Chris so instead we’ll try find bugs which are exploitable without memory corruption.

File and URL handler configuration on Linux desktops

Desktop environments such as GNOME or KDE ship with a list of known file types and default applications. When a user opens a file, the desktop environment first determines the file format and then launches the corresponding application. Ubuntu stores a set of .desktop files for its default applications in the /usr/share/applications/ directory. We want to see which default applications are responsible for a particular file type (MimeType) and run with the filename passed as an argument.

Many of the listed applications are frequently audited software such as image viewers, media players, LibreOffice and Firefox. Instead we are going to look for less commonly researched software which can also be spawned by a default file handler. Apport, Ubuntu’s default crash handler and crash reporting software is first on our list. Let’s see what file types it will handle:

Great, GNOME should open all files matching the mime-type text/x-apport with the apport-gtk tool. Ubuntu determines mime-types based on Mime descriptions in the /usr/share/mime/ directory. Typically the file extension will be used to determine the file type, however the desktop environment can fallback to matching a pattern (a set of magic bytes) in the file if the file extension is unrecognized.

In the case of Apport both a file extension .crash and a magic byte sequence are specified. The desktop environment will try to match the file extension first before comparing magic byte. As the Apport crash file descriptor has a byte pattern we can potentially create an exploit file without a strange .crash extension.

A quick test shows that Ubuntu will open any unknown file with apport-gtk if it begins with “ProblemType: “:

Crash file opened automatically by apport-gtk

Apport looks like a good candidate! It’s installed by default and it’s registered as a default file handler. Let’s try and understand what Apport is meant to do.

Auditing Apport

Ubuntu has shipped the Apport crash handling software with all of its recent Desktop releases. It contains a handful of different components which work together to capture crash reports, display them to user, and upload those reports to the Ubuntu issue tracker. An overview of these components is provided on the Ubuntu wiki.

/usr/share/apport/apport is called when the system detects an application crash. To keep the performance impact to a minimum Apport records a minimal set of information at crash time such as the executable path and a core dump. This minimal crash report is written to /var/crash/[executable_path].[uid].crash.

The update-notifier daemon in Gnome keeps an inotify watch on the /var/crash directory. Whenever there is something new, it calls /usr/share/apport/apport-checkreports. If new reports are found apport-checkreports calls /usr/share/apport/apport-gtk to the display the crash report GUI to the user. apport-gtk is also the application called when .crash files are opened on the desktop environment.

Apport-GTK parses the crash files and displays a minimal crash report prompt to the user. The Apport prompt will be familiar sight to anyone who has used Ubuntu desktop.

Typical Apport prompt

Apport crash report format

The Apport software reads and writes crash reports in its custom crash report format. This plaintext format is partially described on the Apport wiki page.

There are many potential fields which can be used to store information about the crash and about the current system state. The minimal file created at crash time just contains essential entries such as the ProblemType, ExecutablePath and the CoreDump.

When opened apport-gtk collects some more basic information to display a helpful interface to the user. Package information is retrieved based on the executable path and this is used to provide a more friendly application name and icon in the prompt.

Python code injection in the crash file

Apport can submit crash reports to different Ubuntu Launchpad projects depending on which software crashed. Package specific hook scripts (loaded from /usr/share/apport/package-hooks/) can customize the contents and destination of the crash report. The destination project can also be specified with a CrashDB field in the crash report file.

The CrashDB configurations are stored in the /etc/apport/crashdb.conf.d directory. A CrashDB field can be used to load a specific config file from this directory.

Problematically there is also code which loads the CrashDB configuration directly from the CrashDB field and not from a local file. The code first checks if the CrashDB field starts with { indicating the start of a Python dictionary. If found, Apport will call Python’s builtin eval() method with the value of the CrashDB field. eval() executes the passed data as a Python expression which leads to straight forward and reliable Python code execution.

The vulnerable code was introduce on 2012-08-22 in Apport revision 2464. This code was first included in release 2.6.1. All Ubuntu Desktop versions 12.10 (Quantal) and later include this vulnerable code by default.

Exploiting the code injection bug

The following is a minimal crash report file which exploits the CrashDB vulnerability in order to gain arbitrary code execution and open the Gnome calculator:

This code can be saved with the .crash extension, or with any extension that is not registered on Ubuntu.

Apport typically reads a subset of the fields in the crash file in order to prepare the GUI which prompts the user to submit a bug report. The CrashDB field is not parsed and executed until after the user agrees to submit the bug report. However when ProblemType: Bug is set in the crash file, Apport-GTK will switch to the streamlined Bug GUI which causes the CrashDB field to be parsed and executed without any further user interaction.

Apport will spend some time trying to gather information about the crash process if the report does not already contain a Stracktrace field. This delays the execution of the CrashDB field. An empty Stracktrace field in exploit file causes Apport to skip this slow code path.

Apport ships with a number of CrashDB implementations. I have selected the memory implementation as it does not upload crash reports to public bug tracking service.

Path traversal when loading hook scripts

Packages on Ubuntu can install Apport hook scripts to the /usr/share/apport/package-hooks directory. These Python hook scripts are loaded based on the distribution package name. They allow package maintainers to collect useful package specific crash information from users’ computers. However the Package field from the crash report file is used without sanitization when building a path to the package hook files.

This code allows for a path traversal attack and the execution of arbitrary Python scripts outside the system hook_dirs (/usr/share/apport/general-hooks/ or /usr/share/apport/package-hooks/). The _run_hook function simply executes the contents of a provided hook file as Python code. An attacker could serve plant a malicious .py file and a crash file in the users Download directory to get code execution. This scenario is made much easier by Chromium which automatically downloads files without prompting.

The path traversal vulnerability was introduced on 2007-01-24 in Apport 0.44. This version was first released with Ubuntu 7.04 (Feisty).

Using the CrashDB or hook injection bugs for privilege escalation (with user interaction)

All crash files owned by a uid < 500 are considered system crash files. When opening system crash files apport-crashreports will use PolicyKit to prompt the desktop user for root privileges. The prompt is a generic “System program problem detected” message which does not provide any information to the user about the crash.

If a crash file exploiting either of these bugs is placed in /var/crash by a user with uid < 500, and the user accepts the prompt, then code execution can be gained as root. While user interaction is required, people who have used Ubuntu for any period of time will be used to seeing these privilege prompts after random crashes.

Apport system application crash prompt

A bug like this allows a low-privileged application to cross privilege boundaries. For example an SQL injection bug could be used to write a crash file to the world-writable /var/crash directory by using the "INTO OUTFILE" clause. This crash file would then be automatically executed when a desktop user logs in.


Both of these issues were reported to the Apport maintainers and a fix was released on 2016-12-14. The CrashDB code injection issue can be tracked with CVE-2016-9949 and the path traversal bug with CVE-2016-9950. An additional problem where arbitrary commands can be called with the “Relaunch” action is tracked by CVE-2016-9951. I’d like to thank Martin Pitt and the Ubuntu security team for getting a fix released so quickly. They have been a pleasure to work with.

I would encourage all security researchers to audit free and open source software if they have time on their hands. Projects such as Tor, Tails, Debian and Ubuntu all need more eyes for audits which can improve the safety of the internet for everyone. There are lots of bugs out there which don’t need hardcore memory corruption exploitation skills. Logic bugs can be much more reliable than any ROP chain.

The computer security industry has a serious conflict of interest right now. There is major financial motivation for researchers to find and disclose vulnerability to exploit brokers. Many of the brokers are in the business of keeping problems unfixed. Code execution bugs are valuable. As a data point, I received an offer of more than 10,000 USD from an exploit vendor for these Apport bugs. These financial motivators are only increasing as software gets more secure and bugs become more difficult to find.

To improve security for everyone we need to find sustainable ways to incentivize researchers to find and disclose issues and to get bugs fixed. We can’t and we shouldn’t rely on researchers giving away their work for free to for-profit vendors. We will not get security like that.

Microsoft and Google have shown a good example with their vulnerability reward programs. The Internet Bug Bounty is also doing great work and helping to support research on critical internet software. I hope that they can continue the program and expand their scope in the future. I hope we can cooperatively build a shared and secure internet together.


2016-12-09: Apport maintainer contacted
2016-12-10: Response and private bug ticket opened
2016-12-14: Fixed Apport packages released.

Problems using an OpenPGP smartcard for SSH with gpg-agent

I have been using an OpenPGP smartcard for encryption, signing and authentication for over a year now and I’ve found it to be really useful as a root of trust. I have all my systems locked down to only allow public key authentication as a 2 factor security mechanism. While the Free Software Foundation Europe have a good guide about setting up a OpenPGP smartcard using subkeys and offline backups  its unfortunately still not very straight forward to get the card set up.

Recently the EEPROM on my first card died and I had to replace the card. However after setting up the new card with the respective subkeys I  consistently encountered an error from gpg-agent where it was looking for the previous card to be inserted during SSH authentication:

Please insert the card with serial number xxxxxxxxxxxxxxxxx

Please remove the current card and insert the one with serial number xxxxxxxxxxxxxxxxx

Via the magicsauce of strace I eventually determined that gpg-agent was attempting to load the key and card data from a file in ~/.gnupg/private-keys-v1.d/ which referenced the original smartcard. Resolving this issues was as simple as removing the key file in that directory, logging out and logging back into the user account, and finally running the following commands with the card inserted to reload the desired key into the agent.

$ gpg --card-status
$ gpgkey2ssh [KEYID]
$ ssh-add -l

At this stage  ssh-add -l should list your correct card serial number and you will again be able to authenticate over SSH with the card.

Coinbase – Owning a Bitcoin Exchange Bug Bounty Program

When I first started analyzing the Coinbase website I had a quick look over the site layout and the functionality/attack surface available for potential exploitation. I quickly determined it was running Ruby on Rails based on the encoding of the “_coinbase_session” cookie. This was supported by the fact Coinbase’s founder Brian Armstrong had a lot of Ruby snippets on his Github Gist and some more Ruby questions on his Stack Overflow account.

1. Reflected XSS.

Previously I have had some successes finding XSS vulnerabilities in Flash .swf files on some sites. I quickly saw references to a file, in the main CSS file. I recalled reading an advisory about this swf file before, but on first tests it did not appear to be exploitable. This .swf file is typically bundled with ZeroClipboard10.swf. In this case it was also uploaded but not referenced. Bingo! We have found a reflected XSS vulnerability on Coinbase with a known vulnerability in third party code (CVE-2013-1808).

Flash-based XSS on Coinbase.comI reported the vulnerability to Coinbase but @Ciaranmak, who referred me to the Coinbase bug bounty program had reported it independently a few hours before. The Coinbase team still sent me 1 BTC for it.

Continue reading

Trawling Tor Hidden Service – Mapping the DHT

Update 2013-08-15: I have been really enthused by reactions I received to this blog post. It has been referenced from Forbes, Gawker and the Daily Mail and a number of people have been in contact about tracking the DHT for themselves. I would recommend the IEEE S&P paper, “Trawling for Tor Hidden Services: Detection, Measurement, Deanonymization” which presents the same issues allowing the DHT to be trawled. They also present some very serious attacks allowing an adversary to locate hidden services with practical resources. It is well worth checking out if you have an interest in Tor.

Tor hidden services have got more media attention lately as a result of some notorious sites like the Silk Road marketplace, an online black market. On a basic level, Tor hidden services allow you to make TCP services available while keeping your server’s physical location hidden via the Tor anonymity network.


  • Tor hidden service directories (HSDir’s) receive a subset of hidden service look-ups from users, allowing them to map relative popularity/usage of hidden service.
  • An adversary with minimal resources can carry out complete DoS attacks of Tor hidden services by running malicious Tor hidden service directories and positioning them in a particular part of the router list.
  • Many look-ups for Tor hidden services go to the incorrect hidden service directories which negatively affects the initial time to access the site.
  • Hidden services such as are popular, sites such as the Silk Road marketplace receive more than 60,000 unique user sessions a day.


For users to access a hidden service they must first retrieve a hidden service descriptor. This is a short signed message created by the hidden service approximately every hour contain a list of introduction nodes and some other identifying data such as the descriptor id (desc id). The desc ID is based on a hash of some hidden service information and it changes every 24 hours. This calculation is outlined later in the post. The hidden service then publishes its updated descriptor to a set of 6 responsible hidden service directories (HSDir’s) every hour. These responsible HSDir’s are regular node on the Tor network which have up-time longer than 24 hours and which have received the HSDir flag from the directory authorities. The set of responsible HSDir’s is based on their position of the current descriptor id in a list of all current HSDir’s ordered by their node fingerprint. This is an implementation of a simple DHT (Distributed Hash Table).

Continue reading