From 22adb50845bf4af7b1d6fd78e2515c3387356ce1 Mon Sep 17 00:00:00 2001 From: Reepca Russelstein Date: Mon, 21 Oct 2024 00:04:32 -0500 Subject: [PATCH] website: Add 2024-10-21 security advisory post * website/posts/2024-10-21-security-advisory.md: new file. --- website/posts/2024-10-21-security-advisory.md | 212 ++++++++++++++++++ 1 file changed, 212 insertions(+) create mode 100644 website/posts/2024-10-21-security-advisory.md diff --git a/website/posts/2024-10-21-security-advisory.md b/website/posts/2024-10-21-security-advisory.md new file mode 100644 index 0000000..8850da7 --- /dev/null +++ b/website/posts/2024-10-21-security-advisory.md @@ -0,0 +1,212 @@ +title: Build User Takeover Vulnerability +author: Caleb Ristvedt +tags: Security Advisory +date: 2024-10-21 06:00 +--- +A security issue has been identified in +[`guix-daemon`](https://guix.gnu.org/en/manual/devel/en/html_node/Invoking-guix_002ddaemon.html) +which allows for a local user to gain the privileges of any of the build users +and subsequently use this to manipulate the output of any build. Specifically, +this exploit requires the ability to start a derivation build and the ability to +run arbitrary code with access to the store in the root PID namespace on the +machine the build occurs on. As such, this represents an increased risk +primarily to multi-user systems and systems using dedicated privilege-separation +users for various daemons: without special sandboxing measures, any process of +theirs can take advantage of this vulnerability. + +# Vulnerability + +For a very long time, `guix-daemon` [has helpfully made the outputs of failed +derivation builds +available](https://git.savannah.gnu.org/cgit/guix.git/tree/nix/libstore/build.cc?id=e951a375a01262dfd470ee343baf7c41dbc6ff58#n1371) +at the same location they were at in the build container. This has aided greatly +especially in situations where test suites require the package to already be +installed in order to run, as it allows one to re-run the test suite +interactively outside of the container when built with `--keep-failed`. This +transferral of store items from inside the chroot to the real store was +implemented with a simple `rename()`, and no modification of the store item or +any files it may contain. + +If an attacker starts a build of a derivation that creates a binary with the +setuid and/or setgid bit in an output directory, then, and the build fails, that +binary will be accessible unaltered for anybody on the system. The attacker or a +cooperating user can then execute the binary, gain the privileges, and from +there use a combination of signals and procfs to freeze a builder, open any file +it has open via /proc/$PID/fd, and overwrite it with whatever it wants. This +manipulation of builds can happen regardless of which user started the build, so +it can work not only for producing compromised outputs for commonly-used +programs before anybody else uses them, but also for compromising any builds +another user happens to start. + +A related vulnerability was also discovered concerning the outputs of +*successful* builds. These were +[moved](https://git.savannah.gnu.org/cgit/guix.git/tree/nix/libstore/build.cc?id=e951a375a01262dfd470ee343baf7c41dbc6ff58#n2343) - +also via `rename()` - outside of the container prior to having their +permissions, ownership, and timestamps +[canonicalized](https://git.savannah.gnu.org/cgit/guix.git/tree/nix/libstore/build.cc?id=e951a375a01262dfd470ee343baf7c41dbc6ff58#n2429). This +means that there also exists a window of time for a successful build's outputs +during which a setuid/setgid binary can be executed. + +In general, any time that a build user running a build for some submitter can +get a setuid/setgid binary to a place the submitter can execute it, it is +possible for the submitter to use it to take over the build user. This situation +always occurs when `--disable-chroot` is passed to `guix-daemon`. This holds +even in the case where there are no dedicated build users, and builds happen +under the same user the daemon runs as, as happens during `make check` in the +guix repository. Consequently, if a permissive umask that allows execute +permission for untrusted users on directories all the way to a user's guix +checkout is used, an attacker can use that user's test-environment daemon to +gain control over their user while `make check` is running. + +# Mitigation + +This security issue (tracked [here](https://issues.guix.gnu.org/73919) for GNU +Guix) has been fixed by +[two](https://git.savannah.gnu.org/cgit/guix.git/commit/?id=558224140dab669cabdaebabff18504a066c48d4) +[commits](https://git.savannah.gnu.org/cgit/guix.git/commit/?id=5ab3c4c1e43ebb637551223791db0ea3519986e1). Users +should make sure they have updated to the second commit to be protected from +this vulnerability. Upgrade instructions are in the following section. If there +is a possibility that a failed build has left a setuid/setgid binary lying +around in the store by accident, run `guix gc` to remove all failed build +outputs. + +The fix was accomplished by sanitizing the permissions of all files in a failed +build output prior to moving it to the store, and also by waiting to move +successful build outputs to the store until after their permissions had been +canonicalized. The sanitizing was done in such a way as to preserve as many +non-security-critical properties of failed build outputs as possible to aid in +debugging. After applying these two commits, the guix package in guix was +[updated](https://git.savannah.gnu.org/cgit/guix.git/commit/?id=5966e0fdc78771c562e0f484a22f381a77908be0) +so that guix-daemon deployed using it would use the fixed version. + +If you are using `--disable-chroot`, whether with dedicated build users or not, +make sure that access to your daemon's socket is restricted to trusted +users. This particularly affects anyone running `make check` and anyone running +on GNU/Hurd. The former should either manually remove execute permission for +untrusted users on their guix checkout or apply [this +patch](https://issues.guix.gnu.org/73924), which restricts access to the +test-environment daemon to the user running the tests. The latter should adjust +the ownership and permissions of `/var/guix/daemon-socket`, which can be done +for Guix System users using the new `socket-directory-{perms,group,user}` fields +in [this patch](https://issues.guix.gnu.org/73925). + +A proof of concept is available at the end of this post. One can run this code +with + +```sh +guix repl -- setuid-exposure-vuln-check.scm +``` + +This will output whether the current `guix-daemon` being used is vulnerable or +not. If it is vulnerable, the last line will contain `your system is not +vulnerable`, otherwise the last line will contain `YOUR SYSTEM IS VULNERABLE`. + +# Upgrading + +Due to the severity of this security advisory, we strongly recommend +all users to upgrade their `guix-daemon` immediately. + +For a Guix System the procedure is just reconfiguring the system after +a `guix pull`, either restarting `guix-daemon` or rebooting. For +example, + +```sh +guix pull +sudo guix system reconfigure /run/current-system/configuration.scm +sudo herd restart guix-daemon +``` + +where `/run/current-system/configuration.scm` is the current system +configuration but could, of course, be replaced by a system +configuration file of a user's choice. + +For Guix running as a package manager on other distributions, one +needs to `guix pull` with `sudo`, as the `guix-daemon` runs as root, +and restart the `guix-daemon` service. For example, on a system using +systemd to manage services, + +```sh +sudo --login guix pull +sudo systemctl restart guix-daemon.service +``` + +Note that for users with their distro's package of Guix (as opposed to +having used the [install +script](https://guix.gnu.org/en/manual/devel/en/html_node/Binary-Installation.html)) +you may need to take other steps or upgrade the Guix package as per +other packages on your distro. Please consult the relevant +documentation from your distro or contact the package maintainer for +additional information or questions. + +# Conclusion + +Even with the sandboxing features of modern kernels, it can be quite challenging +to synthesize a situation in which two users on the same system who are +determined to cooperate nevertheless cannot. Guix has an especially difficult +job because it needs to not only realize such a situation, but also maintain the +ability to interact with both users itself, while not allowing them to cooperate +through itself in unintended ways. Keeping failed build outputs around for +debugging introduced a vulnerability, but finding that vulnerability because of +it enabled the discovery of an additional vulnerability that would have existed +anyway, and prompted the use of mechanisms for securing access to the guix +daemon. + +I would like to thank Ludovic Courtès for giving feedback on these +vulnerabilities and their fixes - discussion of which led to discovering the +vulnerable time window with successful build outputs - and also for helping me +to discover that my email server was broken. + +## Proof of Concept +Below is code to check if a `guix-daemon` is vulnerable to this exploit. Save +this file as `setuid-exposure-vuln-check.scm` and run following the instructions +above, in "Mitigation." + +```scheme +(use-modules (guix) + (srfi srfi-34)) + +(define maybe-setuid-file + ;; Attempt to create a setuid file in the store, with one of the build + ;; users as its owner. + (computed-file "maybe-setuid-file" + #~(begin + (call-with-output-file #$output (const #t)) + (chmod #$output #o6000) + + ;; Failing causes guix-daemon to copy the output from + ;; its temporary location back to the store. + (exit 1)))) + +(with-store store + (let* ((drv (run-with-store store + (lower-object maybe-setuid-file))) + (out (derivation->output-path drv))) + (guard (c (#t + (if (zero? (logand #o6000 (stat:perms (stat out)))) + (format #t "~a is not setuid: your system is not \ +vulnerable.~%" + out) + (format #t "~a is setuid: YOUR SYSTEM IS VULNERABLE. + +Run 'guix gc' to remove that file and upgrade.~%" + out)))) + (build-things store (list (derivation-file-name drv)))))) +``` + +### About GNU Guix + +[GNU Guix](https://guix.gnu.org) is a transactional package manager +and an advanced distribution of the GNU system that [respects user +freedom](https://www.gnu.org/distros/free-system-distribution-guidelines.html). +Guix can be used on top of any system running the Hurd or the Linux +kernel, or it can be used as a standalone operating system +distribution for i686, x86_64, ARMv7, AArch64, and POWER9 machines. + +In addition to standard package management features, Guix supports +transactional upgrades and roll-backs, unprivileged package +management, per-user profiles, and garbage collection. When used as a +standalone GNU/Linux distribution, Guix offers a declarative, +stateless approach to operating system configuration management. Guix +is highly customizable and hackable through +[Guile](https://www.gnu.org/software/guile) programming interfaces and +extensions to the [Scheme](http://schemers.org) language. -- 2.45.2