TOCTOU vulnerability in _get_ignore_dom (report.py)
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
Apport |
Fix Released
|
Critical
|
Unassigned | ||
apport (Ubuntu) |
Fix Released
|
Undecided
|
Unassigned |
Bug Description
Dear Ubuntu Security Team,
I would like to report a privilege escalation vulnerability in Apport. The vulnerability is a TOCTOU which enables me to trick Apport into reading any file on the system and including it in a crash report file.
I have attached a proof-of-concept which triggers the vulnerability. I have tested it on an up-to-date Ubuntu 18.04. Run it as follows:
bunzip2 PoC.tar.bz2
tar -xf PoC.tar
cd PoC
make
./gencrashreport /etc/shadow
At this point the following file has been created:
/var/crash/
You can use the apport-unpack tool to decompress this file. If you look at the contents of the CoreDump file then you will see that it contains the contents of /etc/shadow (or whichever other file you passed on the command line of gencrashreport).
The bug has a couple of mitigations:
1. My PoC does not work if a file named /var/crash/.lock already exists and is owned by root. This file will only exist if Apport has previously generated a crash report. Based on an informal survey of my own 4 computers (yes - maybe I don't need that many), it usually does not exist (unless the computer is used for security research).
2. The generated crash report file, /var/crash/
To improve the effectiveness of the first mitigation, I would recommend that you make sure that /var/crash/.lock is created (and owned by root) by the Ubuntu installer and/or whoopsie when it starts up. It does not fix the root cause though, which I will describe next.
This is the source location of the TOCTOU vulnerability:
Apport allows the user to place a file in their home directory named `~/.apport-
Here's a summary of how the PoC works:
1. Start a /bin/sleep and kill it with a SIGSEGV.
2. Apport starts up to generate a crash report for /bin/sleep
3. Replace ~/.apport-
4. Wait until Apport drops privileges so that we can kill it with a SIGTRAP.
5. A second Apport starts up to generate a crash report for the first Apport.
6. The second Apport writes out a crash report for the first, containing a copy of the forbidden file in the core dump.
Apport tries quite hard to not run recursively on itself, so I had to jump through a few hoops to make the PoC work:
1. Apport sets a lock on /var/crash/.lock, using lockf. But locks created by lockf are only "advisory". If I own the file, then I can replace it with a different file, thereby deactivating the lock. This is why my PoC only works if /var/crash/.lock doesn't already exist. I need to create it before Apport does, so that I can maintain ownership of it.
2. Apport has signal handlers for most of the core-generating signals, like SIGSEGV. But it doesn't have a handler for SIGTRAP, so that's what my PoC uses.
3. Apport is started with an RLIMIT_CORE value of 1, which is another recursion detection mechanism (see https:/
As I mentioned earlier, I have also found a few other vulnerabilities in whoopsie and Apport. I will file them as separate bugs and include a link to this issue.
Please let me know when you have fixed the vulnerability, so that I can coordinate my disclosure with yours. For reference, here is a link to Semmle's vulnerability disclosure policy: https:/
Thank you,
Kevin Backhouse
Semmle Security Research Team
Related branches
- Apport upstream developers: Pending requested
-
Diff: 32 lines (+13/-3)1 file modifiedapport/report.py (+13/-3)
CVE References
information type: | Private Security → Public Security |
Changed in apport: | |
status: | New → Fix Committed |
Changed in apport: | |
milestone: | none → 2.21.0 |
status: | Fix Committed → Fix Released |
importance: | Undecided → Critical |
Thanks for reporting this issue, and for the great description and reproducer. We will investigate it shortly and will assign a CVE number. Thanks!