PEN-200 Series, Part 2: Passive and Active Information Gathering

What you can learn without sending a single packet, what leaks through HTTP headers, a verified nmap service fingerprint against a real target, and a live recon example run against eresus-ctf-lab.

9 min read
ibrahimsql
1,680 words

PEN-200 Series, Part 2: Passive and Active Information Gathering

The series plan is in the OSCP+ preparation guide; Part 1 covered note-taking and report writing. Now the module where your notes actually start filling up: information gathering.

PEN-200 splits this into passive (never touching the target) and active (talking to it directly). The split isn't cosmetic — what you learn passively decides which ports you scan first, in what order, and how loud you're willing to be during the active phase.

Passive: without sending a single packet

WHOIS

Domain registration data: registration date, registrar, sometimes name servers. Older WHOIS records can leak a real employee's name through a technical contact email — useful for social engineering or username guessing later.

whois target-domain.com

Search engine dorks

site:, filetype:, and inurl: find pages that are indexed but never linked from the target's own navigation:

site:target.com filetype:pdf
site:target.com inurl:admin
site:target.com "index of /"

Netcraft and certificate transparency

Netcraft shows a site's hosting history and technology stack. Certificate transparency logs (crt.sh) are the real find: every TLS certificate ever issued for a target, which routinely surfaces subdomains like staging., dev., or internal- that were never announced anywhere else.

curl -s "https://crt.sh/?q=target.com&output=json" | jq -r '.[].name_value' | sort -u

(Many restricted or corporate networks — including the sandbox this series is written in — block outbound access to crt.sh specifically. If that command hangs or the connection is refused, that's the network, not the syntax; confirm with curl -v before assuming the technique doesn't work.) The CT log approach beats brute-forcing subdomains because it only ever returns names that genuinely had a certificate issued — no wordlist, no false negatives from a list that didn't happen to contain the right word.

DNS zone transfer (AXFR) — worth trying, rarely open

A misconfigured name server will hand you its entire zone file — every record it holds — to anyone who asks:

dig axfr @ns1.target.com target.com

Correctly configured DNS restricts AXFR to secondary name servers only, so most attempts return Transfer failed or time out. That's not a reason to skip it — the configuration mistake is common enough that checking takes one command, and PEN-200's own module calls this out explicitly as a step worth never skipping, precisely because it's free when it fails and total when it doesn't.

Shodan

A search engine over internet-facing services, their banners, and usually their version strings. If you know the target's IP range, Shodan has already scanned it for you — no packets from your own machine required.

Security headers and TLS

This one you can verify right now, against a real site — it's entirely passive, a single ordinary HTTP request:

Bash
$ curl -sI https://anthropic.com
HTTP/1.1 200 Connection Established
 
HTTP/2 301
content-security-policy: default-src 'self'; script-src 'self' 'unsafe-inline' ...
strict-transport-security: max-age=3600
server: cloudflare

server and x-powered-by leak the stack. A missing content-security-policy (or a loose one with unsafe-inline) answers "why does this matter" the moment you later write up an XSS finding. A missing strict-transport-security is its own finding, no further digging required.

Active: talking to the target

From here, every example is run against my own eresus-ctf-lab repo — a target I own and control.

DNS enumeration

$ dig A github.com +short
140.82.114.4

An A record resolves everywhere; MX, TXT, and NS queries get filtered on some networks. Verify what your own environment allows before exam night, not during it. Check every subdomain you find at both the DNS and HTTP layer — some exist in DNS with nothing behind them, and some respond over HTTP via virtual-host routing without ever showing up in DNS at all.

Port scanning

Fast and wide first, across every port; a detailed scan only on what's open. Order matters: running -sV across all 65535 ports is slow and needlessly loud.

Bash
$ nmap -Pn -sT -p 8080,8081 127.0.0.1
 
PORT     STATE SERVICE
8080/tcp open  http-proxy
8081/tcp open  blackice-icecap
 
$ nmap -Pn -sT -sV -p 8080 127.0.0.1
 
PORT     STATE SERVICE VERSION
8080/tcp open  http    Node.js Express framework

-sV correctly fingerprinted what's actually running (Node.js/Express) in the second scan — verify this yourself by running eresus-ctf-lab with npm start and the same command.

The detail that matters here: I'm scanning the lab from the same machine it's running on, which is why 8081 (the internal service) shows up at all. From a different machine, that port would never appear — it's bound to 127.0.0.1, closed to the outside. The NoSQL injection series' SSRF section exploits exactly this gap: reaching a service that isn't externally reachable by making the server itself act as the proxy.

NSE: nmap's scripting engine

-sC runs nmap's default script set — a curated, low-risk subset of the full NSE library (the default and safe categories; nmap also ships vuln, exploit, brute, dos, and others you opt into explicitly, and --script-help <name> shows which category any script belongs to and exactly what it checks). Against the lab, three scripts fired automatically and all three told us something real:

Bash
$ nmap -Pn -sT -sC -sV -p 8080 127.0.0.1
 
PORT     STATE SERVICE VERSION
8080/tcp open  http    Node.js Express framework
|_http-title: Eresus Internal Portal
| http-robots.txt: 2 disallowed entries
|_/api/legacy/ /internal/
|_http-open-proxy: Proxy might be redirecting requests

http-title and http-robots.txt are exactly what they sound like — and note that http-robots.txt did the recon from the earlier section for you, automatically, as a side effect of a routine -sC scan. http-open-proxy is more interesting: it's a false positive. The lab isn't an open proxy; the script's heuristic (send a request that looks like a proxy request, see if the response looks forwarded) got tripped up by something else in how Express responds. This is normal and important to internalize early: NSE scripts are heuristics, not ground truth. Every flagged result needs a manual check before it goes in a report — confirming (or ruling out) http-open-proxy here takes one manual curl through the "proxy" to see it doesn't actually forward anywhere.

For a known CVE against a fingerprinted service, the vuln category is the next step, run deliberately and separately from the default scan because some of its scripts are intrusive enough to crash a fragile service:

nmap -Pn -p 8080 --script vuln 127.0.0.1

Content discovery: default scans miss POST-only routes

This is the part that catches people who treat content-discovery tools as infallible. gobuster, ffuf, feroxbuster, and friends default to GET requests. A route that only responds to POST is invisible to a default scan — even with the exact correct path in your wordlist:

Bash
$ curl -s -o /dev/null -w "%{http_code}\n" localhost:8080/api/legacy/v1/session
404
 
$ echo -n "legacy/v1/session" > exact.txt
$ gobuster dir -u http://127.0.0.1:8080/api -w exact.txt -q
# (no output — gobuster's default GET request 404s, same as curl above)
 
$ curl -s -o /dev/null -w "%{http_code}\n" -X POST localhost:8080/api/legacy/v1/session \
    -H 'Content-Type: application/json' -d '{}'
400

Same exact path, two different HTTP methods, two different results. The route is real — 400 means it received the request and rejected the body, not that it doesn't exist — but a GET-only brute force reports it as a miss. This is also why the robots.txt leak from the passive section mattered more here than brute-forcing: it told you the path and that it belonged to a legacy session API, which is enough to guess POST is worth trying even before you've confirmed the method any other way. When a content-discovery scan comes back emptier than you expected on a target that uses a JSON API, that's the first thing to check — rerun with -m POST (or your tool's equivalent) before concluding nothing is there.

A second gap worth knowing: a flat wordlist of single segments (admin, api, internal, legacy, backup) found nothing at all against the bare root of this app, because every real route here is nested two or three segments deep (/api/legacy/v1/session, /internal/healthz). Flat wordlists find flat applications; a modern API needs either a wordlist built from the application's own naming conventions (framework defaults, the client-side JS bundle's route strings, API documentation left exposed) or a recursive scan that brute forces one segment, then brute forces again inside whatever it found.

SMB, SMTP, SNMP enumeration

The rest of PEN-200's active information gathering module. Standard syntax:

Bash
# SMB — shares, logon policy, OS version
smbclient -N -L //$TARGET
enum4linux-ng -A $TARGET
 
# SMTP — username validation (VRFY/EXPN still open on some servers)
nc $TARGET 25
VRFY root
 
# SNMP — often left open with the "public" community string
snmpwalk -v2c -c public $TARGET

SNMP (161/udp) is especially valuable: when it's open, it often dumps every network interface, the routing table, and sometimes the running process list in plaintext — no exploit required at all.

Combining passive and active: an example from our own lab

eresus-ctf-lab's home page (passive — one HTTP request) hands you a support email:

$ curl -s localhost:8080/ | grep -A1 support@
Having trouble signing in? Contact
<a href="mailto:support@eresus.lab">support@eresus.lab</a>.

robots.txt (also passive) points at two more directories:

Bash
$ curl -s localhost:8080/robots.txt
User-agent: *
Disallow: /api/legacy/
Disallow: /internal/

Those two passive observations — a username hint (support) and a legacy endpoint path — are the starting point of the entire chain in NoSQL Injection, Part 1. The passive phase told you where to aim before the active phase discovered anything at all, which is exactly why PEN-200 teaches them as separate modules.

What goes in your notes

Per Part 1's template, this stage fills in the "Ports" and "Services" subsections under "Enumeration." Paste the raw nmap output verbatim, then add one line above it: which port led where. Someone reading your report six months later — or you, exhausted on exam night — should be able to rebuild your methodology from that one line alone.

Part 3 covers vulnerability scanning: systematically checking what each service you found might be vulnerable to, with Nessus and nmap's NSE scripting engine.

---
Share this post:

What do you think?

React to show your appreciation

Related Posts