root escalation with fs.suid_dumpable=2

Bug #1452239 reported by Marc Deslauriers on 2015-05-06
258
This bug affects 1 person
Affects Status Importance Assigned to Milestone
Apport
High
Martin Pitt
apport (Ubuntu)
High
Martin Pitt
Precise
Undecided
Unassigned
Trusty
Undecided
Unassigned
Utopic
Undecided
Unassigned
Vivid
Undecided
Unassigned
Wily
High
Martin Pitt

Bug Description

Sander Bos discovered that Apport enabled a user to perform a root escalation since it now configures fs.suid_dumpable=2.

Here's a brief description of the issue:
1- A regular user can trigger a coredump with /proc/$PID/stat as root:root simply by doing chmod u-r
2- The root-owned coredump will then be written in the CWD, which in the PoC is /etc/logrotate.d
3- logrotate will gladly skip parts of the coredump it doesn't understand and will successfully run the parts it does

I've set a CRD of 2015-05-21 (original proposal: 2015-05-12) for the publication of this issue.

I have assigned CVE-2015-1324 to this issue.

We can either:

1- Disable fs.suid_dumpable=2
2- Stop creating core dump files when they are to be created as root
3- Create root-owned core dump files in a well-known location

----------------

Here is the original report from Sander Bos (now with the CVE number included):

OVERVIEW
--------

Date: 2015-05-05
Bug name: SCORE: Simple Coredump-Oriented Root Exploit
CVE: CVE-2015-1324
Author: Sander Bos
Author's e-mail address: sbos _at_ sbosnet _dot_ nl

SUMMARY
-------

I found a combination of vulnerabilities to lead to privilege escalation
(root exploitation) by local users in Ubuntu releases 12.04 up to and
including 15.04. Depending on configuration, remote exploitation might
be possible as well. Local exploitation can even be done as the local,
passwordless LightDM "Guest" account user on systems supporting it --
indeed: from anonymous guest user to root.

DESCRIPTION
-----------

The Apport package creates user core dumps in the crashed process'
CWD, and does so since Bazaar revision number 602 [1] / release 0.59.
This is okay, but not always: there is a flaw in the fact that Apport
also does this, as root, for tainted/protected binaries (setuid() and
friends, capabilities(7) enabled binaries, non-readable binaries) when
the sysctl(8)'s fs.suid_dumpable variable is set to 2 (see core(5)).
This means that users can create core dumps as root, in arbitrary
directories which are otherwise write-protected for those users.

In short: Apport should _not_ create user core dumps in the CWD in dump
mode 2 for such tainted binaries; it should either not make user core
dumps at all then, or if possible use a designated and safe directory
for that.

All Ubuntu releases starting with 12.04 have the Apport service enabled by
default [2] (and Ubuntu has Apport installed by default for much longer).

All Ubuntu releases starting with 12.04 (or patched that way after
their release) have sysctl(8)'s fs.suid_dumpable set to 2 by default,
through the Apport package; see bug #1194541, "Create core dumps for
setuid binaries", 2013-06-25 [3].

Along with solving that bug (that is, adding the "missing feature" of
setuid core dumps), the patch to that bug report actually created a root
exploit hole in the upcoming release 13.10, as well as being backported
into the at that time supported Ubuntu releases 12.04, 12.10 and 13.04.

The exact Apport package versions (with their Ubuntu releases) that were
"patched" to have fs.suid_dumpable set to "2" are:

2.0.1-0ubuntu17.4 (Ubuntu 12.04)
2.6.1-0ubuntu12 (Ubuntu 12.10)
2.9.2-0ubuntu8.3 (Ubuntu 13.04)

The value fs.suid_dumpable=2 remained in Ubuntu ever since. The exception
to this is the systemd Apport script in Ubuntu 15.04: the option setting
fs.suid_dumpable to "2" was forgotten to be enabled here, although in the
Upstart script in Ubuntu 15.04 the option is still enabled. I recently
contacted the Apport package maintainer to make sure the systemd script
will not enable the option, as that would enable the root hole in 15.04
with systemd (which is the default init system) as well. Please note:
15.04 with systemd being safe regarding this vulnerabilty has nothing
to do with systemd itself.

Please note that even though Ubuntu has the value of fs.suid_dumpable set
to 2 in releases 12.04 and later, Apport itself has been creating user
coredumps (to CWD, and also with fs.suid_dumpable=2) since Ubuntu 7.04,
which has Apport package release 0.76/0.76.1. Any system since Ubuntu
7.04 that has had fs.suid_dumpable set to 2, even though it wasn't
Ubuntu's default, has been exploitable. Thus, the proof of concept
attached will and should essentially work on any Ubuntu release starting
with 7.04; it was in fact tested and found to be working on 7.04 itself,
but later releases until 12.04 were not tested.

VULNERABLE RELEASES
-------------------

The proof of concept attached should work out of the box on (and is in
fact tested to work on most of them) all of the following releases:

12.04 LTS
12.04.1 LTS
12.04.2 LTS
12.04.3 LTS
12.04.4 LTS
12.04.5 LTS
12.10 (EOL)
13.04 (EOL)
13.10 (EOL)
14.04 LTS
14.04.1 LTS
14.04.2 LTS
14.10
15.04 (only with Upstart, not systemd)

Of all of the above releases all of the Server, Desktop and, where
available, Alternate editions are affected.

In other words: anything Ubuntu from the past three years is vulnerable,
out of the box.

All releases older than 12.04, starting with 7.04, are vulnerable as well
in the sense that they have installed Apport by default or otherwise
provide it as an installable package, being an Apport package which
creates user core dumps (in CWD, also with fs.suid_dumpable=2); however,
those releases do not have the Apport service enabled by default, nor
do they have fs.suid_dumpable set to "2" by default.

OTHER OSes / DISTRIBUTIONS / UBUNTU VERSIONS / DERIVATIVES
----------------------------------------------------------

Any OS / distribution with an Apport version creating a user core
dump (meaning, the core dump created apart from the Apport report in
/var/crash) in CWD is vulnerable. If fs.suid_dumpable=2 is the default,
the OS is exploitable by default.

This may or may not include Ubuntu derivatives, forks and Ubuntu based
distributions like Ubuntu GNOME, Kubuntu, Ubuntu MATE, Ubuntu Studio,
Edubuntu, Lubuntu, Mythbuntu, Xubuntu, Linux Mint (the Ubuntu based
version), Peppermint, elementary OS, Bodhi Linux, BackBox, et cetera[5].
(As a quick test, at least BackBox 3.13 was found to be exploitable
by default.)

Further investigation will need to reveil what OSes / distributions /
Ubuntu versions and derivatives are vulnerable, and which aren't.

WORKAROUND
----------

Disable the Apport service.

PROPOSED IMMEDIATE, TEMPORARY FIX
---------------------------------

Disable suid_dumpable=2 in _all_ Ubuntu Apport packages; let it stay 0,
which is the kernel's default.

Thus, revert the damage done almost two years ago, e.g., by removing
the lines

        echo 2 > /proc/sys/fs/suid_dumpable

and

        echo 0 > /proc/sys/fs/suid_dumpable

from the debian/apport.upstart files.

Additionally, do _not_ enable fs.suid_dumpable=2 in the Apport systemd
scripts for Ubuntu until a proper solution is implemented.

PROPOSED LONG TERM FIX
----------------------

Apport should _never_ dump core to CWD with fs.suid_dumpable=2 for
tainted/protected binaries (just like the kernel does not do this
anymore[4]). If creating a user core dump at all, Apport should dump
it to a safe, dedicated directory.

Apport should use the kernel's "%d" kernel.core_pattern template specifier
(see core(5)), which will present the dumpable state of the crashed
process ("0", "1" or "2"). Please note though that the "%d" template
is only available in (upstream) kernels >=3.7.

REFERENCES
----------

[1] <http://bazaar.launchpad.net/~apport-hackers/apport/trunk/revision/602>
[2] <https://wiki.ubuntu.com/Apport#How_to_enable_apport>
[3] <https://bugs.launchpad.net/ubuntu/+source/apport/+bug/1194541>
[4] <https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=9520628e8ceb69fa9a4aee6b57f22675d9e1b709>
[5] <https://en.wikipedia.org/wiki/List_of_Ubuntu-based_distributions#Ubuntu-based>

CREDITS
-------

The issue was found, analyzed, and reported to Ubuntu by Sander Bos,
along with a detailed explanation of the problem, proposed workarounds
and fixes, and an exploit proof of concept.

Marc Deslauriers (mdeslaur) wrote :

(The reporter has not confirmed my request for a CRD of 2015-05-12)

Martin Pitt (pitti) wrote :

In vivid this is mitigated because the systemd unit doesn't enable suid_dumpable. This was an erroneous omission. However, we should still either fix the bug there or disable it in the upstart job, as I figure a lot of users are still running under upstart.

Changed in apport:
status: New → In Progress
importance: Undecided → High
assignee: nobody → Martin Pitt (pitti)
Martin Pitt (pitti) wrote :

This is the patch targetted at trunk. Note that I already pushed two commits which fix the tests to run properly under suid_dumpable == 2; when I first noticed that the signal_crashes.test_crash_setuid_{keep,drop}() tests started failing after the systemd move I made a bogus change to the tests (r2955):

http://bazaar.launchpad.net/~apport-hackers/apport/trunk/revision/2954
http://bazaar.launchpad.net/~apport-hackers/apport/trunk/revision/2955

The attached patch contains tests, NEWS entry, and detailled explanations in the commit log. I realize it's relatively intrusive, but properly running this with much more restrictive privileges required some special-cases. It shows that drop_privileges() was written in 2006 already, waay before suid_dumpable even existed, so handling uid != euid wasn't an issue back then. Sins of the past... :-(

Next step I'll look into providing backports for all supported releases.

Changed in apport (Ubuntu Wily):
status: New → In Progress
importance: Undecided → High
Martin Pitt (pitti) wrote :

Note that for wily I'll also re-enable suid_dumpable in the systemd job. We probably don't want to bother with this in vivid, I presume?

Martin Pitt (pitti) wrote :

FTR, Marc says that this is producing core files for unpackaged suid root programs, this needs fixing too (and another test case).

Marc Deslauriers (mdeslaur) wrote :

This probably needs changing also:

sys.stderr.write('u: %s g: %s\n' % (real_uid, real_gid))

Marc Deslauriers (mdeslaur) wrote :

CRD is _not_ going to be 2015-05-12. I am awaiting a new CRD from the original bug reporter.

Martin Pitt (pitti) wrote :

Updated patch (against trunk) which more thoroughly suppresses the creation of core files for suid/tainted binaries. New test cases included, too.

For the record, the tests should be run in four modes: as root and user, and with suid_dumpable enabled and disabled:

sudo rm /var/crash/*
echo 0 | sudo tee /proc/sys/fs/suid_dumpable
sudo test/run signal_crashes && test/run signal_crashes
echo 2 | sudo tee /proc/sys/fs/suid_dumpable
sudo rm /var/crash/*
sudo test/run signal_crashes && test/run signal_crashes

Martin Pitt (pitti) wrote :

This is the debdiff for vivid. I have it locally committed to the packaging branch (with four separate commits), and will push them once we release that (except if you make further modifications).

Martin Pitt (pitti) wrote :

Fix and tests backported to utopic.

Martin Pitt (pitti) wrote :

backported fix and tests for trusty

Martin Pitt (pitti) wrote :

and finally, precise debdiff. I again committed these fixes locally in several commits, and will push once you are ready.

Marc Deslauriers (mdeslaur) wrote :

CRD for this issue is 2015-05-21 17:00:00 UTC

Martin Pitt (pitti) on 2015-05-13
description: updated
Martin Pitt (pitti) wrote :

Revised patch for trunk which adds a robustification suggested in bug 1453900: We only read /proc/pid/stat{us} once right after apport starts, before it drops its privileges, to make it more obvious that you can't replace the crashing PID by a new process (with possibly different privileges). As drop_privileges() was called before reading the core dump from stdin, and thus before the originally crashing pid went away, I don't think that there was an actual bug/race here, but like this it's more explicit and cleaner code.

Martin Pitt (pitti) wrote :

updated debdiff for vivid which includes the above /proc reading robustification and the fix for bug 1453900

Martin Pitt (pitti) wrote :

corresponding updated utopic debdiff

Martin Pitt (pitti) wrote :

corresponding updated trusty debdiff

Martin Pitt (pitti) wrote :

corresponding precise debdiff. Note that precise is *not* affected by bug 1453900 (CVE-2015-1325) as the logic of writing core files and .report files was different. At most, a user could replace the written core file with its own contents and thus change the generated .crash report file, but she could just modify the latter directly. I still backported the test case though, it can't hurt to have it.

Launchpad Janitor (janitor) wrote :

This bug was fixed in the package apport - 2.14.7-0ubuntu8.5

---------------
apport (2.14.7-0ubuntu8.5) utopic-security; urgency=medium

  * SECURITY UPDATE: When /proc/sys/fs/suid_dumpable is enabled, crashing a
    program that is suid root or not readable for the user would create
    root-owned core files in the current directory of that program. Creating
    specially crafted core files in /etc/logrotate.d or similar could then
    lead to arbitrary code execution with root privileges. Now core files do
    not get written for these kinds of programs, in accordance with the
    intention of core(5).
    Thanks to Sander Bos for discovering this issue!
    (CVE-2015-1324, LP: #1452239)
  * SECURITY UPDATE: When writing a core dump file for a crashed packaged
    program, don't close and reopen the .crash report file but just rewind and
    re-read it. This prevents the user from modifying the .crash report file
    while "apport" is running to inject data and creating crafted core dump
    files. In conjunction with the above vulnerability of writing core dump
    files to arbitrary directories this could be exploited to gain root
    privileges.
    Thanks to Philip Pettersson for discovering this issue!
    (CVE-2015-1325, LP: #1453900)
  * test_signal_crashes(): Drop hardcoded /tmp/ path in do_crash(),
    test_nonwritable_cwd() uses a different dir.

 -- Martin Pitt <email address hidden> Wed, 13 May 2015 11:59:03 +0200

Changed in apport (Ubuntu Utopic):
status: New → Fix Released
Launchpad Janitor (janitor) wrote :

This bug was fixed in the package apport - 2.0.1-0ubuntu17.9

---------------
apport (2.0.1-0ubuntu17.9) precise-security; urgency=medium

  * SECURITY UPDATE: When /proc/sys/fs/suid_dumpable is enabled, crashing a
    program that is suid root or not readable for the user would create
    root-owned core files in the current directory of that program. Creating
    specially crafted core files in /etc/logrotate.d or similar could then
    lead to arbitrary code execution with root privileges. Now core files do
    not get written for these kinds of programs, in accordance with the
    intention of core(5).
    Thanks to Sander Bos for discovering this issue!
    (CVE-2015-1324, LP: #1452239)
  * Add test case to ensure that users cannot inject arbitrary core dump file
    contents (CVE-2015-1325). This version is not affected, but having the
    test will ensure that backported changes don't introduce this
    vulnerability. (LP: #1453900)
  * test_signal_crashes(): Drop hardcoded /tmp/ path in do_crash(),
    test_nonwritable_cwd() uses a different dir.

 -- Martin Pitt <email address hidden> Wed, 13 May 2015 13:58:17 +0200

Changed in apport (Ubuntu Precise):
status: New → Fix Released
Launchpad Janitor (janitor) wrote :

This bug was fixed in the package apport - 2.14.1-0ubuntu3.11

---------------
apport (2.14.1-0ubuntu3.11) trusty-security; urgency=medium

  * SECURITY UPDATE: When /proc/sys/fs/suid_dumpable is enabled, crashing a
    program that is suid root or not readable for the user would create
    root-owned core files in the current directory of that program. Creating
    specially crafted core files in /etc/logrotate.d or similar could then
    lead to arbitrary code execution with root privileges. Now core files do
    not get written for these kinds of programs, in accordance with the
    intention of core(5).
    Thanks to Sander Bos for discovering this issue!
    (CVE-2015-1324, LP: #1452239)
  * SECURITY UPDATE: When writing a core dump file for a crashed packaged
    program, don't close and reopen the .crash report file but just rewind and
    re-read it. This prevents the user from modifying the .crash report file
    while "apport" is running to inject data and creating crafted core dump
    files. In conjunction with the above vulnerability of writing core dump
    files to arbitrary directories this could be exploited to gain root
    privileges.
    Thanks to Philip Pettersson for discovering this issue!
    (CVE-2015-1325, LP: #1453900)
  * test_signal_crashes(): Drop hardcoded /tmp/ path in do_crash(),
    test_nonwritable_cwd() uses a different dir.

 -- Martin Pitt <email address hidden> Wed, 13 May 2015 11:53:18 +0200

Changed in apport (Ubuntu Trusty):
status: New → Fix Released
Martin Pitt (pitti) wrote :
Changed in apport (Ubuntu Wily):
status: In Progress → Fix Committed
Changed in apport:
status: In Progress → Fix Released
Changed in apport (Ubuntu Wily):
assignee: nobody → Martin Pitt (pitti)
Launchpad Janitor (janitor) wrote :

This bug was fixed in the package apport - 2.17.2-0ubuntu1.1

---------------
apport (2.17.2-0ubuntu1.1) vivid-security; urgency=medium

  * SECURITY UPDATE: When /proc/sys/fs/suid_dumpable is enabled, crashing a
    program that is suid root or not readable for the user would create
    root-owned core files in the current directory of that program. Creating
    specially crafted core files in /etc/logrotate.d or similar could then
    lead to arbitrary code execution with root privileges. Now core files do
    not get written for these kinds of programs, in accordance with the
    intention of core(5).
    Thanks to Sander Bos for discovering this issue!
    (CVE-2015-1324, LP: #1452239)
  * SECURITY UPDATE: When writing a core dump file for a crashed packaged
    program, don't close and reopen the .crash report file but just rewind and
    re-read it. This prevents the user from modifying the .crash report file
    while "apport" is running to inject data and creating crafted core dump
    files. In conjunction with the above vulnerability of writing core dump
    files to arbitrary directories this could be exploited to gain root
    privileges.
    Thanks to Philip Pettersson for discovering this issue!
    (CVE-2015-1325, LP: #1453900)
  * test_signal_crashes(): Drop hardcoded /tmp/ path in do_crash(),
    test_nonwritable_cwd() uses a different dir.
  * signal_crashes test: Fix test_crash_setuid_* to look at whether
    suid_dumpable was enabled.
  * Disable KDE tests for the time being. apport-kde consistently crashes
    in PyQT5 since vivid (LP #1442512), don't block package migration on this.

 -- Martin Pitt <email address hidden> Wed, 13 May 2015 11:42:59 +0200

Changed in apport (Ubuntu Vivid):
status: New → Fix Released
information type: Private Security → Public Security
tags: added: patch
Launchpad Janitor (janitor) wrote :

This bug was fixed in the package apport - 2.17.3-0ubuntu1

---------------
apport (2.17.3-0ubuntu1) wily; urgency=medium

  * New upstream release:
    - SECURITY UPDATE: When /proc/sys/fs/suid_dumpable is enabled, crashing a
      program that is suid root or not readable for the user would create
      root-owned core files in the current directory of that program. Creating
      specially crafted core files in /etc/logrotate.d or similar could then
      lead to arbitrary code execution with root privileges.
      Now core files do not get written for these kinds of programs, in
      accordance with the intention of core(5).
      Thanks to Sander Bos for discovering this issue!
      (CVE-2015-1324, LP: #1452239)
    - SECURITY UPDATE: When writing a core dump file for a crashed packaged
      program, don't close and reopen the .crash report file but just rewind
      and re-read it. This prevents the user from modifying the .crash report
      file while "apport" is running to inject data and creating crafted core
      dump files. In conjunction with the above vulnerability of writing core
      dump files to arbitrary directories this could be exploited to gain root
      privileges.
      Thanks to Philip Pettersson for discovering this issue!
      (CVE-2015-1325, LP: #1453900)
    - apportcheckresume: Fix "occured" typo, thanks Matthew Paul Thomas.
      (LP: #1448636)
    - signal_crashes test: Fix test_crash_setuid_* to look at whether
      suid_dumpable was enabled.
    - test/run: Run UI tests under dbus-launch, newer GTK versions require this
      now.

 -- Martin Pitt <email address hidden> Wed, 20 May 2015 16:58:35 +0200

Changed in apport (Ubuntu Wily):
status: Fix Committed → Fix Released
description: updated
description: updated
Carlos D. Gonzalez (cdgg-cali) wrote :

In Bionic, when apport is enabled fs.suid_dumpable will be set to 2, no matters what you try to set it up using sysctl. Is this the same issue?

To post a comment you must log in.
This report contains Public Security information  Edit
Everyone can see this security related information.

Other bug subscribers