touch-packages team mailing list archive
-
touch-packages team
-
Mailing list archive
-
Message #79691
[Bug 1453900] Re: root escalation via race condition
** Information type changed from Private Security to Public Security
--
You received this bug notification because you are a member of Ubuntu
Touch seeded packages, which is subscribed to apport in Ubuntu.
https://bugs.launchpad.net/bugs/1453900
Title:
root escalation via race condition
Status in Apport crash detection/reporting:
Fix Released
Status in apport package in Ubuntu:
Fix Released
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/apport/apport.
Details
--------------------------------
When a process receives a signal that should generate a coredump,
/usr/share/apport/apport will be invoked by the kernel as root.
On line 284, apport "partially drops privileged":
drop_privileges(pid, True)
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/_bin_sleep.1000.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/_bin_sleep.$uid.crash
2. Spawn a process, chdir("/etc/sudoers.d") and send it SIGSEGV
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/_bin_sleep.$uid.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(os.open(report, os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0), 'wb')
8. Unlink /var/crash/_bin_sleep.$uid.crash
9. Create fifo in /var/crash/_bin_sleep.$uid.crash
10. Write crafted contents to /var/crash/_bin_sleep.$uid.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
---------------------------------
To manage notifications about this bug go to:
https://bugs.launchpad.net/apport/+bug/1453900/+subscriptions