From: Nathan Nye <nnye@whitebeamsec.com>
To: 47229@debbugs.gnu.org
Subject: bug#47229: Hardlink mitigation limits
Date: Tue, 23 Mar 2021 14:18:14 -0400 [thread overview]
Message-ID: <8f95179a-5574-98bd-c44e-f5ee74638dc3@whitebeamsec.com> (raw)
In-Reply-To: <aa062a0d-071c-f015-983e-492cf5cee9d8@whitebeamsec.com>
[-- Attachment #1: Type: text/plain, Size: 3137 bytes --]
Hello,
I'm sharing here for future reference why protected hardlinks alone did
not mitigate the recent LPE security advisory, pre-patch:
"The reasons why are lines 2633 and 2637 of nix/libstore/build.cc:
* https://git.savannah.gnu.org/cgit/guix.git/tree/nix/libstore/build.cc#n2633
* https://git.savannah.gnu.org/cgit/guix.git/tree/nix/libstore/build.cc#n2637
When a package fails to build and the keep failed flag is set
(-K/--keep-failed), it runs a recursive chown on the build directory
(which is writable following guixbuilder01 changing the permissions to
777). It starts at the top level and chowns downwards.
The first important thing to notice here is that at any point (even
pre-chown) the build user has been compromised. The build user can write
a SUID /bin/sh to the build path, and because a normal user can traverse
into the directory before and during the chown, they can run a SUID
shell (allowing them to become guixbuilder01 even after the build user
processes are terminated). Becoming the build user allows multiple paths
to privilege escalation, but in this scenario we have faster ways of
becoming root.
Moving on to getting root, we're choosing not to use a hardlink to show
why it isn't necessary. Instead, we create a directory under the build
directory with thousands of sequentially named files, the final entry
being "passwd" or "shadow". Then we terminate the build and watch for
the first entry to be chowned to our user ID (possibly with the inotify
API). This way, we have opened a lengthy window of time where it is
enumerating over a list of file paths in our chosen directory and
chowning each of them. Now we can execute our TOCTOU race condition
vulnerability.
At the time of check (TOC), the guix-daemon has a list of file paths to
chown under what it assumes is a regular directory (because it ran
S_ISDIR on the directory). But we can swap out the directory from under
it with a symlink to /etc (most efficiently with renameat2() and using
the RENAME_EXCHANGE flag to atomically exchange the paths). At the time
of use (TOU) lchown() only checks if the file /itself/ that is being
chowned is a symlink, not if the path components are, as can be
demonstrated with Python:
$ mkdir td;touch td/tf;python3 -c 'import os;os.lchown("/home/example/td/tf", 1000, 4)';ls -lahtrd td td/tf
-rw-rw-r-- 1 example adm 0 Mar 19 19:20 td/tf
drwxrwxr-x 2 example example 4.0K Mar 19 19:20 td
$ rm -rf td
$ mkdir td; ln -s td td2;touch td2/tf;python3 -c 'import os;os.lchown("/home/example/td2/tf", 1000, 4)';ls -lahtrd td2 td2/tf
lrwxrwxrwx 1 example example 2 Mar 19 19:21 td2 -> td
-rw-rw-r-- 1 example adm 0 Mar 19 19:21 td2/tf
So lchown can blindly chown /etc/passwd to our user by following the
directory symlink and subsequently verifying that passwd itself is not a
symlink. I hope this explains the TOCTOU race condition and why
protected hardlinks help (forcing an attacker to get root using this
race condition), but they are not a solution to the problem (alone)."
- Nathan
[-- Attachment #2: Type: text/html, Size: 4095 bytes --]
next parent reply other threads:[~2021-03-23 20:29 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <aa062a0d-071c-f015-983e-492cf5cee9d8@whitebeamsec.com>
2021-03-23 18:18 ` Nathan Nye [this message]
2021-03-29 15:22 ` bug#47229: Hardlink mitigation limits Ludovic Courtès
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://guix.gnu.org/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=8f95179a-5574-98bd-c44e-f5ee74638dc3@whitebeamsec.com \
--to=nnye@whitebeamsec.com \
--cc=47229@debbugs.gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://git.savannah.gnu.org/cgit/guix.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).