Detect unsafe chroot execution regarding the NSS context. Based on the sudo CVE-2025-32463 vulnerability.
- stable rust toolchains:
rustup toolchain install stable - nightly rust toolchains:
rustup toolchain install nightly --component rust-src - bpf-linker:
cargo install bpf-linker - debug symbols for libc:
sudo apt install libc6-dbg(on debian)
cargo build --release
# Warn mode
RUST_LOG=warn ./unsafe-chroot --libc-path /usr/lib/x86_64-linux-gnu/libc.so.6
# Info mode: verbose output for uprobe and syscall triggers
RUST_LOG=warn ./unsafe-chroot --libc-path /usr/lib/x86_64-linux-gnu/libc.so.6
# pid mode: attach to a specific pid
RUST_LOG=warn ./unsafe-chroot --libc-path /usr/lib/x86_64-linux-gnu/libc.so.6 --pid 1090If RUST_LOG is not set, the program will output nothing.
If --libc-path is not specified, it will look for /usr/lib/libc.so.6.
If --pid is not specified, it will trace all pids.
I herbily recommand to read the original CVE-2025-32463 writeup to understand the work done here.
The glibc avoid reloading nsswitch.conf context when changing root to avoid these kind of issues.
See the related issue tracker and the actual code.
However, if the NSS context is not properly set when chrooting, nsswitch.conf can still be reloaded.
This could result on priviledge escalation in the case of sudo or container escape in Docker CVE-2019-14271.
This project tracks the NSS service databases with eBPF, and check if any of them is null when a chroot occurs.
To track nsswitch.conf reloading in the glibc, the project sets an uprobe on nss_database_check_reload_and_get.
However, this function does not have symbols, and you need glibc debug symbols to resove it.
For now, only debian based distributions are supported. With libc6-dbg, the debug symbols will be loaded from /usr/lib/debug/.build-id.
The following example shows the output of unsafe-chroot when exploiting the sudo CVE-2025-32463 (using this public exploit):
$ RUST_LOG=warn ./unsafe-chroot --libc-path /usr/lib/x86_64-linux-gnu/libc.so.6 &
Attaching nss tracker to offset: 1257216
Waiting for Ctrl-C...
$ sudo -R woot woot
[WARN unsafe_chroot] [1896] Unsafe chroot detected: database id 6 is null
[WARN unsafe_chroot] [1896] Unsafe chroot detected: database id 6 is null
[WARN unsafe_chroot] [1896] Unsafe chroot detected: database id 6 is null
[WARN unsafe_chroot] [1896] Unsafe chroot detected: database id 6 is null
root@debian:/# id
uid=0(root) gid=0(root) groups=0(root),24(cdrom),25(floppy),27(sudo),29(audio),30(dip),44(video),46(plugdev),100(users),101(netdev),1000(user)
root@debian:/# exitThe database id 6 (initgroups) is null, which prevents the reload security when changing root.
Setting the initgroups in /etc/nsswitch.conf will prevent this priviledge escalation:
# Set initgroups database with empty value
$ echo 'initgroups:' | sudo tee -a /etc/nsswitch.conf
$ sudo -R woot woot
sudo: you are not permitted to use the -R option with woot