root escalation via race condition
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
Apport |
Fix Released
|
Critical
|
Unassigned | ||
apport (Ubuntu) |
Fix Released
|
Critical
|
Martin Pitt |
Bug Description
Philip Pettersson reported the following apport security issue:
Original email:
-------
Summary
-------
All (?) versions of the bug reporting program "apport" suffer from a
race condition that allows unprivileged users to create coredumps in
directories owned by root.
This is unrelated to the namespace bug found last month by Tavis Ormandy.
Software description
-------
apport - automatically generate crash reports for debugging
Affected distributions
-------
All versions of Ubuntu Server/Desktop since at least 12.04.
This bug should be present in any version of ubuntu that has apport
enabled in /usr/share/
Details
-------
When a process receives a signal that should generate a coredump,
/usr/share/
On line 284, apport "partially drops privileged":
drop_privilege
However, this has no real security benefit since the euid of the
process will still be root.
On line 394 apport opens a file in /var/crash:
with open(report, 'rb') as f:
"report" is the filename, which can be easily predicted.
If a user with uid 1000 makes /bin/sleep crash, the filename will be:
/var/crash/
The directory /var/crash is world writable.
If we create a fifo in this location before making our program crash,
apport will hang on line 394 until a report is written to that fifo by us.
When apport is in this paused state, we can kill our original process
and keep forking() until we get the same pid again. We then make this process
execute /bin/su which makes our original pid a root process.
The drop_privileges() function on line 49 incorrectly uses the pid
as the indicator as to which uid we should drop privileges to. We can
therefore make apport "drop" privileges to uid 0 and write a corefile
anywhere on the system.
This can be used to write a corefile with crafted contents in /etc/cron.d,
/etc/logrotate.d and so on to gain root privileges.
Additionally, on versions since at least Ubuntu 14.04 is it possible to
completely control the contents of the written corefile. This allows easy
expoitation by leveraging /etc/sudoers.d.
Proof of concept exploit flow
-------
The partial privilege drop on line 284 allows us to send SIGSTOP to apport, which allows us great
control over the execution flow. On line 460 apport will ultimately write
the corefile contents by reading from the report file in /var/crash.
1. Create the fifo /var/crash/
2. Spawn a process, chdir("
3. Send SIGKILL to the process in (2), fork() until we get the same pid
as the process we killed.
4. In our new process, execute /bin/su
5. Send valid report data to /var/crash/
6. Core file is written to /etc/sudoers.d/core as root with perms 0600.
Additionally, on 14.04+ we can do this:
7. Keep sending SIGSTOP/SIGCONT until these lines have been executed:
404: os.unlink(report)
410: reportfile = os.fdopen(
8. Unlink /var/crash/
9. Create fifo in /var/crash/
10. Write crafted contents to /var/crash/
11. Apport will read our fifo at line 155 and create a corefile with our
contents.
Suggested fixes
-------
1. Remove the partial privilege drop. It serves no security purpose and allows
the user to send SIGSTOP to apport, which enables race conditions.
2. Save the uid of the pid at the beginning, do not rely on the pid more than
once since the actual process can change during the course of execution.
3. Drop privileges completely as soon as possible.
4. Make sure the report files are actual files and not FIFOs.
Credit
-------
Philip Pettersson, Samsung Security Center
-------
Changed in apport (Ubuntu): | |
status: | New → In Progress |
importance: | Undecided → Critical |
assignee: | nobody → Martin Pitt (pitti) |
information type: | Private Security → Public Security |
This is CVE-2015-1325