Openwall GNU/*/Linux - a small security-enhanced Linux distro for servers
[<prev] [next>] [day] [month] [year] [list]
Date: Thu, 4 Jan 2018 11:57:45 -0500
From: Michael Orlitzky <michael@...itzky.com>
To: oss-security@...ts.openwall.com
Subject: CVE-2017-18018: GNU chown and chgrp (coreutils) privilege escalation
 via recursive dereferences

Product: GNU chown and chgrp (coreutils)
Versions-affected: 8.29 and earlier (all)
Author: Michael Orlitzky
Bug-report:
http://lists.gnu.org/archive/html/coreutils/2017-12/msg00045.html


== Summary ==

The chown program in GNU coreutils is vulnerable to a race condition
when using the POSIX "-R -L" options to follow symlinks recursively.
In the presence of symlinks, the recursive directory traversal is not
guaranteed to be performed depth-first. As a result, the "new owner" may
be able to introduce a symlink at a point in the traversal that has yet
to be reached. When it is reached, chown will be performed on the target
of that symlink -- a situation that is often exploitable to gain root
privileges.

The chgrp program is implemented with chown and is vulnerable in the
same way when used on group-writable paths.


== Details ==

When calling GNU chown recursively, there is an "obvious" race
condition that is handled correctly:

  mjo $ sudo mkdir -p foo/bar
  mjo $ sudo chown --verbose --recursive mjo foo
  changed ownership of 'foo/bar' from root to mjo
  changed ownership of 'foo' from root to mjo

If the order was switched (that is, if the traversal was not
depth-first), then there would be a period of time where mjo (as the
owner of "foo") could do bad things to "foo/bar" before chown was
called on it. But so far so good: the order above is safe, and chown
does not follow symlinks by default with "--recursive" or "-R".

The bad news: if, in addition, you pass the POSIX "-L" flag to chown,
then the new owner of "foo" can exploit the situation. The main idea
is to use a symlink that points up, to reorder the traversal, and then
to exploit the aforementioned race condition. If you're lucky, the
race can be won with a naive loop in a second shell. The unlucky (or
merely impatient) reader might want to add some sleep() calls after
the printf() statements in src/chown-core.c.

=== Terminal 1 (root) ===

  root # mkdir -p /var/www/chown-test && cd /var/www
  root # mkdir chown-test/foo
  root # mkdir chown-test/bar
  root # ln -s ../bar chown-test/foo/quux
  root # touch chown-test/bar/baz

=== Terminal 2 (mjo) ===

  mjo $ cd /var/www/chown-test/bar
  mjo $ while true; do ln -s -f /etc/passwd ./baz; done;

=== Terminal 1 (root) ===

  root # chown --verbose --recursive -L mjo chown-test
  changed ownership of 'chown-test/foo/quux/baz' from root to mjo
  changed ownership of 'chown-test/foo/quux' from root to mjo
  changed ownership of 'chown-test/foo' from root to mjo
  changed ownership of 'chown-test/bar/baz' from root to mjo
  ownership of 'chown-test/bar' retained as mjo
  changed ownership of 'chown-test' from root to mjo

The verbose output shows that happens. The depth-first traversal
follows the symlink and changes ownership of "foo/quux" (which points
to "bar") before it changes ownership of "bar/baz". Between the two
operations, mjo should be able to replace "bar/baz" with a symlink to
a path of his choosing. Indeed, the attack has worked, because mjo now
owns /etc/passwd:

  root # ls -l /etc/passwd
  -rw-r--r-- 1 mjo root 1.5K 2017-12-17 18:34 /etc/passwd

Note that the "--dereference" flag implies the same problem. Along
with "--recursive", the "--dereference" flag forces you to set either
"-H" or "-L", and in that context, choosing "-H" won't prevent the
link itself from being dereferenced.

The chgrp program is vulnerable in exactly the same way, but to a
lesser extent. With chown, the new owner can always replace files in
the directories that he now owns; with chgrp, those directories need
to be group-writable. But beware that any member of the new group can
try to exploit the situation. The same considerations apply when chown
is used to change groups instead of (or in addition to) ownership.


== Mitigation ==

The two flags "-R" and "-L" are specified by POSIX, so their behavior
can't be changed much. Avoid using chown or chgrp recursively. And if
you do, don't also use "-L".

Powered by blists - more mailing lists

Your e-mail address:

Please check out the Open Source Software Security Wiki, which is counterpart to this mailing list.

Powered by Openwall GNU/*/Linux - Powered by OpenVZ