How I Approach Real-World Pentests (Methodology + Toolkit)
My personal methodology for external + internal pentests — the phases, the tools per phase, the documentation cadence, and a worked example walking from recon to admin-panel takeover.
By Umair Sabir
Penetration testing isn't just running tools. It's the order in which you run them, the notes you take while doing it, and what you do between the tool runs that separates a useful report from a glorified Nessus dump.
This is my actual workflow for a typical 5-day external + internal engagement. It's PTES-flavoured but trimmed to fit how I actually work in practice.
The phases (my version)
I keep them strictly sequential per target but parallel across targets. While my Nmap is sweeping the /22, I'm reading the org's job postings to map their tech stack.
Phase 1 — Recon (OSINT)
The cheapest hour you'll spend on the engagement.
The single most valuable signal in this phase: what's the user format? firstname.lastname@, flastname@, f.lastname@. Pin that and password sprays are 5x more effective.
Phase 2 — Mapping
Now I have a target list. Time to find what's alive and what services it speaks.
# fast TCP discovery on a /22 — 90 seconds
masscan 10.20.0.0/22 -p1-65535 --rate=20000 -oG masscan.gpn
# convert masscan output → nmap-friendly target list
awk '/Host:/ {print $2}' masscan.gpn | sort -u > alive.txt
# detailed enum on what masscan found
nmap -sV -sC -p- -Pn -iL alive.txt --open -oA nmap/full
Tip from too many engagements: the
--openflag on Nmap is the difference between a scan I can read and a 14-megabyte file ofclosedlines I cannot.
Phase 3 — Enumeration (where the actual work happens)
Per-service enumeration is what separates a junior tester from a senior one. The mindset is "what does this service let me do without authenticating, and what does it let me do with credentials I haven't proven yet?"
A non-exhaustive list of my favourite per-service enumerators:
Phase 4 — Exploitation (with manual validation)
The single rule: never blindly run a Metasploit module against a production target. I read the module source first. Yes, every time. If a module says target: linux/http/some_app, I want to know it isn't going to overwrite a config file.
For commodity vulns I keep a small folder of hand-curated PoCs that I trust:
# personal exploit collection — read before running
$ tree ~/exploits/
~/exploits/
├── log4shell/
│ ├── README.md ← my notes on what works
│ ├── jndi.py ← my fork, no callback to attacker.com
│ └── payloads/
├── confluence/
└── ...
🔐 If you can't explain to a customer what the exploit does to their server, don't run it. Refusing is professional. Crashing prod is not.
Phase 5 — Post-exploitation
This is where most of my time goes on internal engagements. Phase 4 might take 30 minutes. Phase 5 takes three days. Almost all of it is data collection and pivot mapping — I covered the AD-specific version of this in Active Directory Attack Paths.
The minimum I want before I leave a host:
- Local hashes (
secretsdump.py -local) - Recently logged-on users (LSASS dump, Mimikatz)
- Cached domain credentials (DCC2 hashes from registry)
- Schtasks / cron / WMI subscriptions (for persistence audit)
- Network reachability map (
nmapfrom this host's perspective)
Phase 6 — Reporting
A finding is not a finding until it has:
- Evidence — screenshot or HTTP transcript with timestamps.
- Reproduction — exact command, exact payload.
- Impact — what does an attacker do with this? Don't write "information disclosure"; write "attacker reads
/etc/passwdenabling username enumeration for password spraying". - Remediation — concrete, vendor-specific fix.
I write reports in Markdown, render to PDF via Pandoc + a custom Lua template. Sample header per finding:
A worked example: bypassing auth by guessing the URL
This is a sanitised version of a real engagement. A web app behind Nginx; the login page worked exactly as you'd expect. I noticed in the JS bundle a reference to /admin/dashboard.php — but the link was hidden behind a role === 'admin' check.
What if there was no server-side check? I just typed it in:
That's it. No exploit. No payload. Just a missing requireAuth() middleware on a route the developer assumed nobody would type.
The lesson isn't "old apps are bad". The lesson is server-side authorization is non-negotiable and the URL is the most accessible attack surface in your application.
TL;DR
- Phase order matters more than tool choice. Most beginners skip recon and pay for it in phase 4.
- Manual validate everything. Tools lie. Reports based on tool output without manual confirm get junior testers fired.
- Documentation is the deliverable. The shell is for you. The report is for the customer.
- Stay legal. Scope, scope, scope.
If you want the offensive flavour applied to AD specifically, my Active Directory Attack Paths post is the natural next read. Common beginner traps live in Top 10 Pentesting Mistakes.