commit ff5fb8249205c8b4b97f8fc18a2dac6c6530d34f
parent 17d3afee9d348b61305ec9a78169866657454dd9
Author: $: DAΞMON <zer0sec.xp@icloud.com>
Date: Thu, 17 Sep 2026 05:42:16 +0100
Add SMTP user enumeration and Amass cheat sheets
New enumeration/ pages: smtp-user-enum.pl + swaks + nmap smtp-enum-users
(grouped, all three answer "does this mailbox exist"), and Amass v5 (its
CLI changed significantly from v3/v4 - intel folded into enum, results
live in a graph DB read back via `subs`). Written and version-checked
against the tools as actually installed/run on this machine.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Diffstat:
3 files changed, 291 insertions(+), 1 deletion(-)
diff --git a/content-manifest.json b/content-manifest.json
@@ -1217,6 +1217,47 @@
"difficulty": "intermediate",
"action": "port",
"note": "Distinct undo/recovery focus not covered by the main Git sheet."
+ },
+ {
+ "source": "local",
+ "rel": "smtp-user-enum + swaks + nmap smtp-enum-users",
+ "category": "enumeration",
+ "slug": "smtp-user-enum",
+ "title": "SMTP User Enumeration",
+ "description": "smtp-user-enum, swaks and nmap smtp-enum-users \u2014 VRFY/EXPN/RCPT enumeration, open-relay checks, manual SMTP probing.",
+ "tools": [
+ "smtp-user-enum",
+ "swaks",
+ "Nmap"
+ ],
+ "tags": [
+ "enumeration",
+ "smtp",
+ "email"
+ ],
+ "difficulty": "beginner",
+ "action": "add",
+ "note": "New sheet: written after installing smtp-user-enum/swaks on the attacker Mac; nmap smtp-enum-users already bundled."
+ },
+ {
+ "source": "local",
+ "rel": "amass v5.1.1",
+ "category": "enumeration",
+ "slug": "amass",
+ "title": "Amass",
+ "description": "OWASP Amass v5 subdomain enumeration and attack-surface mapping \u2014 enum, ASN/CIDR discovery, reading results out of its graph database.",
+ "tools": [
+ "Amass"
+ ],
+ "tags": [
+ "enumeration",
+ "osint",
+ "recon",
+ "dns"
+ ],
+ "difficulty": "intermediate",
+ "action": "add",
+ "note": "New sheet: v5 rewrote the CLI (OAM graph DB, engine subcommand, intel folded into enum) vs the v3/v4-era commands still shown in passive-external-recon.md."
}
]
-}
+}
+\ No newline at end of file
diff --git a/src/content/sheets/enumeration/amass.md b/src/content/sheets/enumeration/amass.md
@@ -0,0 +1,114 @@
+---
+title: "Amass"
+description: "OWASP Amass v5 subdomain enumeration and attack-surface mapping — enum, ASN/CIDR discovery, and reading results back out of its graph database."
+category: enumeration
+tags: [enumeration, osint, recon, dns]
+tools: [Amass]
+difficulty: intermediate
+updated: "2026-09-17"
+---
+
+# Amass
+
+OWASP Amass performs passive-by-default subdomain enumeration and attack-surface mapping, combining certificate transparency logs, passive DNS sources, search engines, and (optionally) active techniques like zone-transfer attempts and DNS brute-forcing. It's typically the first name-gathering pass alongside subfinder/assetfinder in [Stage 00 — Passive External Recon](/sheets/pentest-workflow/passive-external-recon).
+
+> [!warning] Version note — v5 changed the CLI shape
+> Amass v5 rewrote storage around a local graph database (the "OAM" — Open Asset Model) served by a background **engine** process. Older tutorials referencing `amass intel -asn`, `amass intel -whois`, or `amass enum -o results.txt` are describing v3/v4 and **do not apply to v5** — there is no `intel` subcommand anymore; ASN/CIDR discovery moved directly into `enum`, and results live in the graph DB, read back out with `amass subs` rather than a plain output file. Confirmed against v5.1.1 (`amass -version`).
+
+## Subcommands (v5)
+
+```text
+amass enum interface with the engine that performs enumerations
+amass subs analyze and present discovered subdomains and associated data
+amass track diff OAM data to identify newly discovered assets since a timestamp
+amass viz generate graph visualizations (DOT / GEXF) from OAM data
+amass assoc query the OAM along an association "triple" walk
+amass engine run/manage the collection engine that backs the OAM database
+```
+
+`amass enum` auto-starts the background engine the first time it's needed (`ps aux | grep amass` will show `amass engine` running afterward); it stays up across invocations so repeated `enum`/`subs` calls against the same domain reuse the same graph DB. Stop it with `pkill -f "amass engine"` if you want a clean slate.
+
+## `amass enum` — the main pass
+
+```bash
+# passive is the DEFAULT in v5 — this alone is the safe, non-contact baseline
+amass enum -d $DOMAIN
+
+# multiple domains in one run
+amass enum -d $DOMAIN,$DOMAIN2
+
+# active mode: adds zone-transfer attempts + cert-name grabs against the target's own infra
+amass enum -d $DOMAIN -active
+
+# brute force on top of the passive/active sources, with a custom wordlist
+amass enum -d $DOMAIN -brute -w /path/to/subdomains.txt
+
+# ASN/CIDR-driven discovery — folded directly into `enum` in v5 (no more `intel` subcommand)
+amass enum -asn 12345
+amass enum -cidr 203.0.113.0/24 -d $DOMAIN
+
+# seed from names you already have (other tools' output), skip re-discovering them
+amass enum -d $DOMAIN -nf known_subs.txt
+
+# write files out under a directory instead of just the graph DB
+amass enum -d $DOMAIN -oA ./recon/amass_$DOMAIN
+```
+
+| Flag | Description | Default |
+|---|---|---|
+| `-d value` | Domain(s), comma-separated | — |
+| `-df file` | File of domains | — |
+| `-active` | Attempt zone transfers + cert-name grabs (this is what makes a run "active", not a `-passive` flag — that flag still exists but is a no-op since passive is now default) | off |
+| `-brute` | Run DNS brute forcing after the search/API sources | off |
+| `-w file` / `-aw file` | Wordlist for brute forcing / name alterations | — |
+| `-alts` | Generate altered/permuted names from what's found | off |
+| `-asn value` | ASN(s), comma-separated — org-wide discovery | — |
+| `-cidr value` | CIDR(s), comma-separated | — |
+| `-addr value` | IPs/ranges (`192.168.1.1-254`) | — |
+| `-p value` | Ports to check when resolving | 80, 443 |
+| `-r` / `-tr value` | Untrusted / trusted DNS resolver IPs | system default |
+| `-nf file` | Seed with already-known names (skips re-discovery) | — |
+| `-bl value` / `-blf file` | Blacklist subdomains (inline / from file) | — |
+| `-timeout N` | Minutes with no progress before terminating | 30 |
+| `-oA prefix` | Path prefix for all output files | — |
+| `-dir path` | Directory holding the graph database | default state dir |
+| `-list` | Print all available data source names | — |
+| `-include` / `-exclude value` | Restrict to / drop specific data sources | all |
+| `-v` | Verbose/debug output | off |
+| `-silent` | No output during the run | off |
+
+> [!tools] Related in the same recon stage
+> [subfinder](https://github.com/projectdiscovery/subfinder), [assetfinder](https://github.com/tomnomnom/assetfinder), and [puredns](https://github.com/d3mondev/puredns) (wildcard-aware resolving) — see [Stage 00](/sheets/pentest-workflow/passive-external-recon) for unioning all of them together. No single passive source is complete; run at least two and merge.
+
+## Reading results back out
+
+Amass v5 doesn't dump to stdout the way older versions did — query the graph DB with `subs` after `enum` finishes:
+
+```bash
+amass subs -d $DOMAIN -names # just the discovered names, one per line
+amass subs -d $DOMAIN -ip # names + IPs
+amass subs -d $DOMAIN -ipv4 # IPv4 only
+amass subs -d $DOMAIN -summary # ASN table summary instead of names
+amass subs -d $DOMAIN -names > subs_amass.txt # pipe into the union step alongside subfinder/assetfinder
+```
+
+## Diffing over time & visualizing
+
+```bash
+# only assets discovered since a given time — good for re-scanning a target periodically
+amass track -d $DOMAIN -since '09/01 00:00:00 2026 UTC'
+
+# export the asset graph
+amass viz -dir <graph-db-dir> -dot -oA ./recon/amass_graph
+amass viz -dir <graph-db-dir> -gexf -oA ./recon/amass_graph # open the .gexf in Gephi
+```
+
+> [!warning] Watch out
+> - `-active` sends zone-transfer attempts and TLS connections straight at the target's own nameservers/hosts — that's active recon, not passive; keep engagements scoped accordingly (same rule as [Stage 00's `amass enum -passive` note](/sheets/pentest-workflow/passive-external-recon), now spelled `-active`'s absence rather than a `-passive` flag's presence).
+> - API keys for VirusTotal/SecurityTrails/Shodan/Censys etc. (`amass enum -list` shows all sources) meaningfully increase yield — configure them in the YAML config (`-config`) rather than relying on the free/keyless sources alone.
+> - The background engine persists between runs; if a `subs`/`track` query looks stale, confirm you're pointed at the same `-dir` the `enum` run used, or that the engine process is even still the one you expect (`ps aux | grep amass`).
+
+## Sources
+
+- https://github.com/owasp-amass/amass
+- `amass -h`, `amass enum -h`, `amass subs -h`, `amass track -h`, `amass viz -h` (v5.1.1, confirmed locally)
diff --git a/src/content/sheets/enumeration/smtp-user-enum.md b/src/content/sheets/enumeration/smtp-user-enum.md
@@ -0,0 +1,134 @@
+---
+title: "SMTP User Enumeration"
+description: "smtp-user-enum, swaks and nmap's smtp-enum-users — VRFY/EXPN/RCPT username enumeration, open-relay checks and manual SMTP probing."
+category: enumeration
+tags: [enumeration, smtp, email]
+tools: [smtp-user-enum, swaks, Nmap]
+difficulty: beginner
+updated: "2026-09-17"
+---
+
+# SMTP User Enumeration
+
+Three ways to answer "does this mailbox exist?" against an SMTP server (25/465/587): the purpose-built **smtp-user-enum.pl** (bulk VRFY/EXPN/RCPT), **nmap**'s bundled `smtp-enum-users` script (same three methods, one-shot with the rest of a scan), and **swaks** for hand-crafted probes — relay testing, `RCPT TO` acceptance checks, and STARTTLS/auth testing that the dedicated enumerators don't do. Start with `nmap -sC -p25 $IP` (the `smtp-commands` script) to see which of VRFY/EXPN/AUTH/STARTTLS the server even advertises before picking a method. For the full protocol-level workflow (open relay, spray, CVE-2020-7247) see [Service Enumeration → SMTP](/sheets/pentest-workflow/service-enumeration) and [Attacking Common Services → Email](/sheets/pentest-workflow/attacking-common-services).
+
+## smtp-user-enum.pl
+
+Perl script (pentestmonkey), preinstalled on Kali; on macOS clone it — `git clone https://github.com/pentestmonkey/smtp-user-enum`, no dependencies beyond core Perl (`Net::SMTP`, `Getopt::Std`). Runs one method against a wordlist with configurable concurrency.
+
+```bash
+# VRFY (default method) — most reliable when not disabled
+perl smtp-user-enum.pl -M VRFY -U users.txt -t $IP
+
+# EXPN — expands a mailing list/alias to member addresses
+perl smtp-user-enum.pl -M EXPN -U users.txt -t $IP
+
+# RCPT — works even when VRFY/EXPN are disabled; needs a MAIL FROM domain
+perl smtp-user-enum.pl -M RCPT -U users.txt -D $DOMAIN -t $IP
+
+# single username check, custom port, more workers
+perl smtp-user-enum.pl -M VRFY -u root -t $IP -p 25 -m 10
+```
+
+| Flag | Description | Default |
+|---|---|---|
+| `-M mode` | Method: `VRFY`, `EXPN`, or `RCPT` | `VRFY` |
+| `-u user` | Single username to check | — |
+| `-U file` | File of usernames | — |
+| `-t host` | Single target host | — |
+| `-T file` | File of target hosts | — |
+| `-D dom` | Domain appended to usernames for `RCPT` mode (guess full addresses) | none |
+| `-f addr` | `MAIL FROM` address, `RCPT` mode only | `user@example.com` |
+| `-p port` | TCP port | 25 |
+| `-m n` | Max concurrent processes | 5 |
+| `-d` | Debug output | off |
+| `-v` | Verbose | off |
+
+> [!warning] Watch out
+> - Many hardened MTAs (Postfix in particular) leave VRFY enabled but always return `252 Cannot VRFY user` regardless of validity — calibrate first by testing one known-bad and one known-good username; if both give identical responses, VRFY is neutered and you need `RCPT` instead.
+> - `RCPT` mode is slow (~5–7 requests/sec) and the noisiest of the three since it opens a full `MAIL FROM`/`RCPT TO` sequence per guess (no `DATA` sent, so no mail is actually delivered) — scope the wordlist, don't point it at rockyou.
+> - `-m` concurrency above ~10–15 gets rate-limited or blacklisted by most modern MTAs.
+
+## nmap `smtp-enum-users`
+
+Same three methods, run as part of an nmap scan — convenient when you're already scanning the port and want a same-command result, or need nmap's `userdb`/`passdb`-style scripted output.
+
+```bash
+# default: tries RCPT, then VRFY, then EXPN, against nmap's built-in username list
+nmap -p25 --script smtp-enum-users $IP
+
+# pick methods and order explicitly
+nmap -p25 --script smtp-enum-users --script-args smtp-enum-users.methods={EXPN,RCPT,VRFY} $IP
+
+# custom username list (standard nmap unpwdb 'userdb' argument)
+nmap -p25 --script smtp-enum-users --script-args userdb=/opt/users.txt $IP
+
+# banner/capability check first — shows if VRFY/EXPN/STARTTLS/AUTH are even offered
+nmap -p25 -sC -sV $IP
+```
+
+Stops early if the server enforces authentication, and prints whatever usernames it found before any error. Related scripts on the same target: `smtp-commands` (EHLO/HELP capability banner), `smtp-open-relay` (tries hardcoded `MAIL FROM`/`RCPT TO` combinations to detect relaying — flags authenticated servers as not-vulnerable rather than erroring), `smtp-vuln-cve2010-4344` / `smtp-vuln-cve2011-1720` (Exim/Postfix heap overflows).
+
+```bash
+nmap -p25 --script smtp-commands,smtp-open-relay,smtp-vuln* $IP
+```
+
+## swaks — manual probing, relay & auth testing
+
+swaks doesn't bulk-enumerate on its own, but it's the right tool for anything smtp-user-enum/nmap don't cover: single-shot `RCPT TO` acceptance checks (useful when VRFY/EXPN are both off), open-relay testing, and exercising STARTTLS/AUTH.
+
+```bash
+# basic connectivity / banner + EHLO capabilities
+swaks --to test@$DOMAIN --server $IP
+
+# RCPT-based user check — stop right after RCPT TO, read the response code
+# (accepted, 250/251 = valid mailbox; 550/551/553 = no such user)
+swaks --to victim@$DOMAIN --from test@evil.com --server $IP --quit-after RCPT --hide-all; echo "exit: $?"
+
+# same idea, scripted over a userlist (swaks exits non-zero on rejection)
+for u in $(cat users.txt); do
+ swaks --to "$u@$DOMAIN" --server $IP --quit-after RCPT --hide-all \
+ && echo "VALID: $u"
+done
+
+# open relay test — external sender AND external recipient, neither in the local domain
+swaks --to outsider@external-test.com --from spoofed@some-other-domain.com --server $IP
+# accepted (250) with no auth from an address outside $DOMAIN, to an address outside $DOMAIN = open relay
+
+# force/require STARTTLS, dump the peer cert
+swaks --to test@$DOMAIN --server $IP --tls --tls-get-peer-cert
+
+# authenticated send (validate creds found via spraying/loot)
+swaks --to test@$DOMAIN --from user@$DOMAIN --server $IP \
+ --auth LOGIN --auth-user 'user@$DOMAIN' --auth-password 'Password1!'
+```
+
+| Flag | Description | Default |
+|---|---|---|
+| `-t, --to ADDR` | Envelope recipient (only truly required option) | — |
+| `-f, --from ADDR` | Envelope sender; `<>` for null sender | best-guess local user@host |
+| `-s, --server HOST[:PORT]` | Target server | localhost |
+| `--port PORT` | Override port | protocol default (25) |
+| `--protocol PROTO` | `SMTP`, `ESMTP`, `SSMTP`, `SMTPS`, `LMTP`, … — sets port/TLS/HELO type as a side effect | `ESMTP` |
+| `--quit-after STOP` | End the transaction cleanly right after a stage: `CONNECT`, `HELO`/`EHLO`, `STARTTLS`, `AUTH`, `MAIL`, `RCPT` | full transaction |
+| `-tls` | Require STARTTLS, abort if unavailable | off |
+| `-tlsc, --tls-on-connect` | Implicit TLS on connect (port 465 style) | off |
+| `-a, --auth [TYPE]` | Require auth: `LOGIN`, `PLAIN`, `CRAM-MD5`, `DIGEST-MD5`, `NTLM` | off |
+| `-au, --auth-user` / `-ap, --auth-password` | Credentials for `--auth` | prompt |
+| `-n, --suppress-data` | Don't print the DATA section (keep output readable) | off |
+| `-ha, --hide-all` | Suppress all output — check `$?` instead | off |
+| `--timeout TIME` | Transaction timeout (`5s`/`3m`/`1h`, `0` = none) | 30s |
+
+> [!tip] `--quit-after RCPT` is the whole trick
+> This is straight from swaks' own quick-start docs: stopping right after `RCPT TO:` gets you the server's accept/reject verdict without ever sending a message body, so it reads almost identically to what `smtp-user-enum -M RCPT` does internally — useful when you want to hand-verify a couple of hits, or when you need swaks' TLS/auth handling that smtp-user-enum doesn't have.
+
+> [!warning] Watch out
+> - Open-relay and unauthenticated `RCPT` probing generate real SMTP session log entries (and, on a relay hit, an actual outbound message) — scope carefully on live/production mail infrastructure, this isn't a passive check.
+> - `--protocol SMTP` forces `HELO` instead of `EHLO`, which some scanners use specifically to dodge servers that only rate-limit/log on ESMTP extensions.
+
+## Sources
+
+- https://github.com/pentestmonkey/smtp-user-enum
+- https://github.com/jetmore/swaks
+- https://nmap.org/nsedoc/scripts/smtp-enum-users.html
+- https://nmap.org/nsedoc/scripts/smtp-open-relay.html