← Back to team overview

touch-packages team mailing list archive

[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