Explore top 10 tips to secure your open-source projects now. Read More

×
Alerts This Week
Warning Icon 1 568
Alerts This Week
Warning Icon 1 568

Linux Privilege Escalation from a Defensive Perspective: Sudoers and SUID Misconfigurations

7.Locks HexConnections Esm H446

Root access on a Linux system rarely arrives through a zero-day.

Honestly, it usually doesn't even arrive through something you'd consider clever. More often — and this shows up in post-incident report after post-incident report — an attacker gets a low-privilege foothold through a misconfigured web app or a reused credential, and then just... looks around. What they find is a sudoers entry that's been sitting untouched since the last sysadmin handed off the server. Or a SUID binary a developer set during a late-night deployment and forgot to mention. Neither makes it into a CVE database. Neither gets a patch advisory. They're just there, waiting for someone to notice them.

The Sudoers File Doesn't Clean Itself

The design intent behind sudoers is reasonable — give specific users specific elevated permissions without distributing actual root credentials. The gap between intent and reality is that entries get written fast, during deployments, when nobody has time to get the scope exactly right, and then they stay. Sysadmins change. The documentation doesn't. Nobody ever schedules an audit. Privilege Escalation Esm W400

The worst version is also probably the most common one to find in the wild:

developer ALL=(ALL) NOPASSWD: ALL

One line. Whoever gets that user account gets the system. No second factor, no password prompt, nothing:

sudo bash

The subtle version — the one that trips up more environments — is when an admin adds something like vim to sudoers thinking it's scoped and safe. It isn't:

sudo vim -c '!bash'

Root shell, three keystrokes. GTFOBins catalogs this exact escalation technique for hundreds of binaries — find, less, python, perl, awk, tar, nmap with --interactive, and on and on. Same pattern across all of them: the binary gets NOPASSWD access, nobody checks whether it can spawn a shell, and the entry stays in place indefinitely because nothing breaks and nobody touches it.

The cp case is less intuitive but just as damaging, maybe more so because it feels innocuous. Copy access to /usr/bin/cp with elevated permissions means an attacker can overwrite /etc/sudoers directly, inject their own NOPASSWD entry, then run bash:

cp /etc/sudoers /tmp/sudoers.bak
echo "$(whoami) ALL=(ALL) NOPASSWD:ALL" >> /tmp/sudoers.bak
cp /tmp/sudoers.bak /etc/sudoers
sudo bash

No exploit code. No CVE required. A misconfigured permissions entry and roughly two minutes.

Two Sudo Vulnerabilities That Got Less Attention Than They Deserved

In mid-2025 two vulnerabilities in sudo itself were disclosed — CVE-2025-32462 and CVE-2025-32463 — that made even correctly written sudoers configurations exploitable. Worth knowing about, because sudo doesn't get treated with the same patch urgency as web application CVEs, and production systems tend to lag on it for exactly that reason.

CVE-2025-32463, the more severe of the two at CVSS 9.3, abused sudo's --chroot option: place a malicious nsswitch.conf in any user-controlled directory and sudo loads an attacker's shared library as root — before it gets around to checking permissions. The flaw was introduced in sudo 1.9.14 (June 2023) and went undetected for about two years before Stratascale's research team found it. CISA added it to the Known Exploited Vulnerabilities catalog in September 2025, months after the patch was already available. Both vulnerabilities were patched in sudo 1.9.17p1, released June 2025. The gap between "patch available" and "patch deployed" in production Ubuntu 22.04 environments stretched well into the second half of the year, because nobody was treating sudo updates as urgent.

The lesson here isn't just "patch sudo" — though that's obviously necessary. It's that a correctly written sudoers file isn't sufficient protection when the underlying binary has an elevation flaw. Defense has to go deeper than configuration.

SUID Binaries: Persistent, Overlooked, and Reliable

SUID is a permission bit — makes a binary execute as its owner regardless of who actually invokes it. Ping, passwd, su, a handful of others all legitimately need it. The problem is when it ends up on things it shouldn't: internal scripts, test binaries, standard utilities that picked up the bit during a misconfigured install and never lost it because nobody was looking.

Every attacker who lands a shell runs this immediately:

find / -perm -4000 -type f 2>/dev/null

Output goes straight to GTFOBins. The non-standard entries — anything outside the expected set of system binaries — are where the actual findings are. Custom internal binaries with SUID set are the first things to dig into.

PATH hijacking is clean and reliable when a custom SUID binary calls system utilities without specifying absolute paths. A script that runs system("service restart") instead of system("/usr/sbin/service restart") is exploitable by anyone who can write to an earlier PATH directory:

cd /tmp
echo "/bin/bash" > service
chmod +x service
export PATH=/tmp:$PATH
./vulnerable-suid-binary

Shell resolves service to the malicious binary, executes it with the SUID binary owner's effective UID. If that's root, escalation is complete — simple as that. Linux Sudo Bug 696x392 Esm W400

Editors with SUID set are a separate category, not just escalation but immediate persistence. If /usr/bin/nano carries the bit, the attacker edits /etc/passwd directly: adds a root-level account with no password, change survives reboots, nothing suspicious in logs beyond a file modification timestamp.

Tools like LinPEAS automate all of this — SUID binaries, sudoers entries, writable cron jobs, kernel version against known CVE databases — in a single run, under sixty seconds. What used to take an experienced attacker thirty minutes of manual enumeration is now a script. Defenders need to understand what that output surfaces and what order it prioritizes findings, because that's the actual methodology being applied on the other side.

Fixing It

Open /etc/sudoers with visudo and actually read through every entry. Any line granting NOPASSWD: ALL to a non-system user either has a documented justification or it gets removed — those are the only two acceptable outcomes. For every binary with NOPASSWD access, look it up on GTFOBins by name. If there's a documented escalation path, that entry is an open door and should be treated as such.

Replace broad grants with precise ones. A user who needs to restart nginx gets exactly that:

# Scoped to one service, one action — nothing broader
username ALL=(root) NOPASSWD: /usr/bin/systemctl restart nginx

Not /usr/bin/systemctl. Definitely not ALL.

For SUID, the approach that actually works is establishing a baseline on a known-good system and comparing against it:

find / -perm -4000 -type f 2>/dev/null > /root/suid-baseline.txt

Store that file somewhere reliable and run comparisons after deployments and package updates. Any new SUID binary outside a planned package install gets investigated. Anything that shouldn't carry the bit gets stripped:

chmod u-s /path/to/binary

Internal scripts should never have SUID set. Development environments sometimes add it for convenience — that needs to come off before anything reaches production, full stop.

Monitoring matters too, and it's worth doing properly rather than just adding a single auditd rule and calling it covered.

A useful starting set watches for sudo execution, SUID-related syscalls, and writes to sensitive files that privilege escalation techniques commonly target:

# Flag all sudo invocations
auditctl -a always,exit -F arch=b64 -S execve -F path=/usr/bin/sudo -k sudo_exec

# Flag setuid/setgid syscalls — catches SUID abuse attempts
auditctl -a always,exit -F arch=b64 -S setuid -S setgid -k priv_escalation

# Flag writes to sudoers and sensitive auth files
auditctl -w /etc/sudoers -p wa -k sudoers_change
auditctl -w /etc/sudoers.d/ -p wa -k sudoers_change
auditctl -w /etc/passwd -p wa -k passwd_change
auditctl -w /etc/shadow -p wa -k shadow_change

Once you have events, ausearch and aureport are how you actually work with the data rather than grepping raw logs:

# Show all sudo-related events in the last hour
ausearch -k sudo_exec --start recent

# Show all sudoers file modifications
ausearch -k sudoers_change

# Summary report of privilege-related events by user
aureport --auth --summary

Parent-child process relationships are the real signal to watch. apache2 → sudo → bash is not a logging anomaly — it's a kill chain in progress. The SUID baseline comparison mentioned above pairs naturally with inotifywait for real-time alerting on new SUID files:

inotifywait -m -r -e attrib /usr/bin /usr/local/bin /usr/sbin 2>/dev/null | \
  grep --line-buffered "ATTRIB" | while read line; do
    echo "[ALERT] Attribute change detected: $line" | logger -t suid_monitor
  done

Run that as a service, and any new SUID bit set outside of a package manager operation generates a log entry immediately. SELinux and AppArmor work alongside all of this — they constrain what a process can do even after it reaches root, containing the blast radius of a successful escalation even when prevention fails. And keep sudo patched — CVE-2025-32463 was in CISA's KEV catalog months after the patch was available, which tells you exactly how many production systems were sitting exposed throughout 2025. SUID Changes Icon Esm W225

The kernel headlines this year — Copy Fail, Fragnesia, Dirty Frag — have most security teams focused on patches and module blacklists. That's reasonable. But those same teams often have sudoers entries that predate everyone currently on staff, and SUID binaries in /usr/local/bin that nobody can account for. Kernel CVEs get CVE numbers and CISA advisories. Misconfigured sudoers entries don't. That asymmetry in attention is precisely why they keep working year after year.

Enumeration tools don't organize findings by category. LinPEAS flags the NOPASSWD entry and the unpatched kernel in the same output, same color coding, same priority. One of them usually comes first.