A penetration test is only as good as the methodology behind it. Firing Nmap at a target and running Metasploit modules is not a pentest — it's a vulnerability scan with extra steps. Real assessments follow a structured process that maximises coverage, maintains evidence integrity, and produces findings clients can prioritise and fix.
Phase 1: Planning & Scoping
Everything starts with a clear Rules of Engagement (RoE) document. Before touching a single target:
- Define scope — IP ranges, domains, application URLs, excluded systems (production databases, third-party SaaS)
- Testing window — hours during which active scanning is permitted
- Emergency contacts — who to call if you accidentally knock something over
- Legal authorisation — signed statement of work or bug bounty programme policy
Without written authorisation, penetration testing is unauthorised access under the Computer Fraud and Abuse Act (and equivalent legislation globally). Don't skip this.
Phase 2: Passive Reconnaissance
Passive recon collects intelligence without sending a single packet to the target. Everything here is legally permissible and produces zero footprint.
OSINT sources:
# Certificate transparency logs reveal subdomains
curl -s "https://crt.sh/?q=%.target.com&output=json" | jq '.[].name_value' | sort -u
# Historical DNS data
dnsx -d target.com -a -cname -mx -resp-only
# Shodan for exposed services
shodan search 'org:"Target Corp"' --fields ip_str,port,transport
People and technology:
- LinkedIn for employee names, job titles, tech stack clues ("experience with AWS RDS", "administers Okta")
- GitHub for leaked credentials, internal tooling, API keys in commit history
- Job postings — "must know Palo Alto firewall administration" tells you exactly what the perimeter looks like
Phase 3: Active Enumeration
Now we interact with the target directly. Document every tool invocation with timestamps.
Port scanning:
# Full TCP scan — slow but thorough
nmap -p- -sV -sC --open -oA scans/full_tcp 10.10.10.0/24
# UDP top ports — often overlooked
nmap -sU --top-ports 200 -oA scans/udp 10.10.10.0/24
Web application enumeration:
# Virtual host discovery
ffuf -w subdomains.txt -u https://target.com -H "Host: FUZZ.target.com" -mc 200,301,302
# Directory and file brute force
feroxbuster -u https://app.target.com -w /usr/share/wordlists/dirb/big.txt -x php,html,js
# JavaScript file analysis — endpoints, secrets, tokens
trufflehog git https://github.com/target/repo --only-verified
Phase 4: Exploitation
Match findings to appropriate exploits. The goal is demonstrating business impact, not running every available module.
Prioritisation framework:
| Finding | Exploitability | Impact | Priority | |---|---|---|---| | Unauthenticated RCE on public API | High | Critical | P0 — exploit immediately | | SQLi in admin panel | Medium | High | P1 — exploit with care | | Misconfigured S3 bucket (read) | Low | Medium | P2 — document access | | Missing security headers | N/A | Low | P3 — note only |
During exploitation:
- Record everything — terminal sessions with timestamps, screenshots, Burp proxy history
- Minimise collateral damage — don't exfiltrate real PII, don't persist unless pivoting requires it
- Use a dedicated attack VM and note your source IPs so the SOC can differentiate you from real attackers
Phase 5: Post-Exploitation
Once you have a foothold, demonstrate the full blast radius of the compromise.
# Credential harvesting from memory (Windows)
mimikatz # sekurlsa::logonpasswords
# Network pivot — route through compromised host
ssh -D 1080 -N user@pivot.internal # SOCKS proxy
proxychains nmap -sT internal.range/24
# Active Directory enumeration
bloodhound-python -u compromised_user -p 'P@ssw0rd' -d target.local -c All
The BloodHound graph often reveals attack paths from a regular domain user to Domain Admin that the client's own team didn't know existed.
Phase 6: Reporting
The report is the product. A client who can't understand or act on your findings gets zero value from the engagement.
Structure:
- Executive Summary — 1 page, business language, no CVE numbers, focus on risk and consequence
- Technical Findings — one page per finding with: description, evidence (screenshots/payloads), CVSS score, remediation steps
- Remediation Roadmap — priority-ordered list the team can paste into a sprint backlog
Writing a finding:
Title: Unauthenticated SQL Injection in
/api/v1/searchRisk: Critical (CVSS 9.8)
Description: The
qparameter is concatenated directly into a SQL query without parameterisation. An unauthenticated attacker can extract the contents of theuserstable, including bcrypt password hashes and session tokens.Evidence:
GET /api/v1/search?q=' UNION SELECT username,password,NULL FROM users--returned [screenshot]Remediation: Replace string concatenation with parameterised queries. Verify no other query construction paths exist in the codebase using SAST (semgrep rule
python.sqlalchemy.security.sqlalchemy-execute-raw-query).
Vague recommendations like "patch your systems" don't get fixed. Specific, actionable guidance does.
Toolchain Summary
| Phase | Tool | |---|---| | Passive recon | Shodan, crt.sh, trufflehog, theHarvester | | Active enum | Nmap, ffuf, feroxbuster, nuclei | | Web app testing | Burp Suite Pro, sqlmap, dalfox | | Post-exploitation | Mimikatz, BloodHound, Impacket | | Reporting | PlexTrac, Ghostwriter, or a well-structured template |
A methodology is not a checklist — it's a framework for thinking. Adapt it to each engagement, document deviations, and always tie technical findings back to the business risk they represent.

