[Bug 1839415] Re: Fully user controllable lock file due to lock file being located in world-writable directory
Francis Ginther
francis.ginther at canonical.com
Wed Oct 30 12:54:00 UTC 2019
** Tags added: id-5d640fd329dff226b88f059a
--
You received this bug notification because you are a member of Ubuntu
Foundations Bugs, which is subscribed to apport in Ubuntu.
https://bugs.launchpad.net/bugs/1839415
Title:
Fully user controllable lock file due to lock file being located in
world-writable directory
Status in Apport:
New
Status in apport package in Ubuntu:
Fix Released
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.
To manage notifications about this bug go to:
https://bugs.launchpad.net/apport/+bug/1839415/+subscriptions
More information about the foundations-bugs
mailing list