Fully user controllable lock file due to lock file being located in world-writable directory

Bug #1839415 reported by Alex Murray on 2019-08-08
This bug affects 1 person
Affects Status Importance Assigned to Milestone
apport (Ubuntu)

Bug Description

Author: Sander Bos, <https://www.sbosnet.nl/>

Date: 2019-07-30

In data/apport, Apport creates a lock file:

     35 # create a lock file
     36 lockfile = os.path.join(apport.fileutils.report_dir, '.lock')
     37 try:
     38 fd = os.open(lockfile, os.O_WRONLY | os.O_CREAT | os.O_NOFOLLOW)

The value of "apport.fileutils.report_dir" is /var/crash/, which is a
world-writable (but sticky) directory.

Placing the lock file in a world-writable directory as done here
effectively makes the lock file fully controllable by any user, at least
as long as the lock file does not already exist, i.e., in case Apport has
not been executed before (but a different issue exists which completely
defeats this precondition).

This issue can be exploited in several ways, with various impacts.

Probably being its most severe impact, a simple shell one-liner like
the following will lead to a complete system DoS, i.e., DoS on the OS
resource level (e.g., memory):

   $ mkfifo /var/crash/.lock && while sleep 100 & do sleep 1; kill -11 "$!"; kill -9 "$!"; done

This will make the os.open() in data/apport stall forever due to the FIFO
file, as well as create more than one and up to an indefinite amount of
(root owned) Apport processes due to the failing of the locking mechanism,
which should normally prevent subsequent Apport processes from running,
because the lock is not yet set at that point. The "kill -9" prevents
the user from hitting its "RLIMIT_NPROC" limit, and "RLIMIT_CORE" itself
does not apply to the root user.

The locking mechanism failing when using a FIFO file, i.e., circumventing
the locking mechanism thus making it possible to run more than one
Apport process at the same time (even when they are in a stalled state)
is an impact on its own, not just in the OS DoS scenario in which it is
abused up to the point creating many Apport instances ultimately leading
to OS DoS.

Also, the issue in the first place leads to DoS for Apport both for
individual instances as well as it as a service as a whole, i.e., making
Apport unable to function, as one user could create a /var/crash/.lock
FIFO file and prevent Apport from doing its work in case of program
crashes of other users.

This issue when used with a FIFO file can also be abused to "time"
Apport, i.e., let Apport stall for some period of time (and do whatever
is needed to control the further flow of Apport during that time, e.g.,
as part of a larger exploit scenario) and have it continue at a specific,
user defined moment by then reading out the FIFO file.

As a different method of exploitation of this issue, a user can simply
create /var/crash/.lock (as a regular file) and put an indefinite lock
on it, thereby preventing Apport from succesfully doing its work, again
leading to service DoS for Apport. Apport DoS could also be achieved by
for example creating /var/crash/.lock as a directory or as a socket file,
meaning Apport can't os.open() /var/crash/.lock as a file, again making
Apport fail (i.e., service DoS).

The above scenarios prevent legitimate Apport processes from creating,
opening and / or locking the lock file, leading to DoS for both invidual
Apport instances as well as Apport as a whole, i.e., service DoS.

Note that the impact of this issue might be even worse on systems without
sysctl(8)'s "fs.protected_symlinks=1" set, which in default installations
provides effective protection due to /var/crash/ being a sticky directory,
or without "fs.protected_hardlinks=1" being set.

Also note that, besides all of the impacts above due to /var/crash/
being world-writable, /var/crash/ isn't a logical location to place a
lock file to begin with; using a more appropriate location like /var/lock/
would make more sense, and is also the proposed fix for this issue.

Changed in apport (Ubuntu):
importance: Undecided → Low
Changed in apport:
importance: Undecided → Low
Seth Arnold (seth-arnold) wrote :

CVE-2019-11485 for the lock file in the wrong directory.


Alex Murray (alexmurray) wrote :

A CRD has been confirmed for this issue - Tuesday next week - 2019/10/29

Launchpad Janitor (janitor) wrote :

This bug was fixed in the package apport - 2.20.1-0ubuntu2.20

apport (2.20.1-0ubuntu2.20) xenial-security; urgency=medium

  * SECURITY UPDATE: apport reads arbitrary files if ~/.config/apport/settings
    is a symlink (LP: #1830862)
    - apport/fileutils.py: drop permissions before reading user settings file.
    - CVE-2019-11481
  * SECURITY UPDATE: TOCTTOU race conditions and following symbolic
    links when creating a core file (LP: #1839413)
    - data/apport: use file descriptor to reference to cwd instead
      of strings.
    - CVE-2019-11482
  * SECURITY UPDATE: fully user controllable lock file due to lock file
    being located in world-writable directory (LP: #1839415)
    - data/apport: create and use lock file from /var/lock/apport.
    - CVE-2019-11485
  * SECURITY UPDATE: per-process user controllable Apport socket file
    (LP: #1839420)
    - data/apport: forward crashes only under a valid uid and gid,
      thanks Stéphane Graber for the patch.
    - CVE-2019-11483
  * SECURITY UPDATE: PID recycling enables an unprivileged user to
    generate and read a crash report for a privileged process (LP: #1839795)
    - data/apport: drop permissions before adding proc info (special thanks
      to Kevin Backhouse for the patch)
    - data/apport, apport/report.py, apport/ui.py: only access or open
      /proc/[pid] through a file descriptor for that directory.
    - CVE-2019-15790

 -- Tiago Stürmer Daitx <email address hidden> Tue, 29 Oct 2019 05:23:08 +0000

Changed in apport (Ubuntu):
status: New → Fix Released
Alex Murray (alexmurray) on 2019-10-30
information type: Private Security → Public Security
tags: added: id-5d640fd329dff226b88f059a
To post a comment you must log in.
This report contains Public Security information  Edit
Everyone can see this security related information.

Duplicates of this bug

Other bug subscribers