Subdomain Enumeration and Attack Surface Mapping with Amass, Subfinder, and httpx

Mobile API OSINT
Time it takes to read this article 6 minutes.

Introduction / Overview

Subdomain enumeration is the foundation of external reconnaissance. Before you can test an application, you have to find it — and modern organizations sprawl across hundreds of hosts: forgotten staging environments, abandoned marketing microsites, internal admin panels accidentally exposed to the internet, and API gateways. Each of these is a potential entry point. The goal of this article is to turn a single root domain into a deduplicated, probed, and prioritized list of live web targets.

Disclaimer: This article is for education and authorized security testing only. Enumerating and probing infrastructure you do not own or have explicit written permission to test (a bug bounty scope, a signed engagement letter) may be illegal in your jurisdiction. Stay inside your authorized scope at all times.

We will chain four tools — amass and subfinder for discovery, httpx for live-host probing, and ffuf for active brute forcing — and explain how certificate transparency (CT) underpins passive enumeration. We close with a Blue Team section, because every technique here leaves traces a defender can hunt for.

How it works / Background

There are two broad classes of subdomain discovery.

Passive enumeration queries third-party data sources without ever touching the target's infrastructure. The richest of these is certificate transparency. Every publicly trusted TLS certificate issued since 2018 must be logged to append-only CT logs (RFC 6962), enforced by browsers like Chrome. Because Subject Alternative Name (SAN) fields list every hostname a cert covers, CT logs leak subdomains the moment a certificate is issued — including hosts that were never meant to be public. Aggregators such as crt.sh, Censys, and the CertSpotter API index these logs. Other passive sources include passive DNS (SecurityTrails, VirusTotal), search engines, and ASN/WHOIS data.

Active enumeration generates DNS queries against the target's authoritative name servers: brute forcing candidate names from a wordlist, permutation/alteration of known names (e.g. dev-api, api-dev), and zone transfer attempts (AXFR). Active methods find hosts that have no certificate and no public footprint, but they are noisier and may breach scope.

Subdomain Enumeration and Attack Surface Mapping with Amass, Subfinder, and httpx diagram 1

The diagram shows the pipeline: discover from passive and active sources, merge and deduplicate, resolve, then probe live hosts with httpx to produce a prioritized target list.

Prerequisites / Lab setup

Install the Go-based tooling from ProjectDiscovery and OWASP. Go 1.21+ is recommended.

# ProjectDiscovery tools
go install -v github.com/projectdiscovery/subfinder/v2/cmd/subfinder@latest
go install -v github.com/projectdiscovery/httpx/cmd/httpx@latest
go install -v github.com/ffuf/ffuf/v2@latest

# OWASP Amass
go install -v github.com/owasp-amass/amass/v4/...@master
Bash

Passive sources are dramatically more productive with API keys. Configure subfinder at ~/.config/subfinder/provider-config.yaml and amass at ~/.config/amass/config.yaml (or datasources.yaml in v4) with free-tier keys for SecurityTrails, VirusTotal, Shodan, Censys, and GitHub. For a lab, target a domain you control or a public bug bounty program with an explicit wildcard scope. The SecLists project provides good wordlists at /usr/share/seclists/Discovery/DNS/.

Walkthrough / PoC

Step 1 — Passive discovery

Start with subfinder for speed, then amass enum -passive for breadth. Keep results in per-tool files so you can audit sources later.

TARGET=example.com

subfinder -d "$TARGET" -all -silent -o subfinder.txt

amass enum -passive -d "$TARGET" -o amass.txt
Bash

Query certificate transparency directly as a sanity check and to catch anything the aggregators missed. crt.sh exposes a JSON endpoint:

curl -s "https://crt.sh/?q=%25.$TARGET&output=json" \
  | jq -r '.[].name_value' \
  | sed 's/\*\.//g' \
  | sort -u > crtsh.txt
Bash

Step 2 — Active discovery (brute force)

ffuf is primarily an HTTP fuzzer, but with virtual-host (Host: header) fuzzing it discovers vhosts that share an IP. For pure DNS resolution brute forcing, puredns or dnsx is the better fit, but ffuf is invaluable for vhost discovery once you know a target IP:

ffuf -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-110000.txt \
  -u "https://$TARGET" \
  -H "Host: FUZZ.$TARGET" \
  -fs 0 -mc 200,301,302,403 -o ffuf-vhost.json
Bash

-fs 0 filters empty responses; tune the filter (size, words, or lines) against a baseline of a known-bad host so the default catch-all page is excluded.

Step 3 — Merge, deduplicate, and resolve

cat subfinder.txt amass.txt crtsh.txt | sort -u > all-subs.txt
wc -l all-subs.txt
Bash

Step 4 — Probe live hosts with httpx

httpx resolves each candidate, follows the host across HTTP/HTTPS and common ports, and enriches every live host with status code, title, technology (via Wappalyzer signatures), CDN detection, and content length — the metadata you need for triage.

httpx -l all-subs.txt \
  -title -status-code -tech-detect -web-server -cdn \
  -follow-redirects \
  -ports 80,443,8080,8443 \
  -json -o httpx.json
Bash

Triage the output: pull out admin panels, dev/staging hosts, and non-CDN origins (which are directly attackable).

jq -r 'select(.status_code==200) | "\(.url) [\(.title)] \(.tech)"' httpx.json \
  | grep -iE 'admin|dev|stage|test|api|jenkins|grafana'
Bash

Step 5 — Hunt for subdomain takeover

Subdomains that resolve to a CNAME pointing at an unclaimed cloud resource (S3, Azure, GitHub Pages, Heroku) are takeover candidates. Flag the dangling ones:

# subs that no longer resolve to a live host are takeover suspects
comm -23 all-subs.txt <(jq -r '.input' httpx.json | sort -u) > dangling.txt
Bash

Verify with a dedicated tool such as subzy or nuclei (-t http/takeovers/) before claiming anything — false positives are common, and you only report what you can prove.

Detection & Defense (Blue Team)

Recon is hard to block outright, but it is detectable and the underlying exposure is fixable. Defenders should weight remediation at least as heavily as offense.

Monitor your own certificate transparency feed. Attackers read CT logs; so should you. Subscribe to crt.sh RSS or run certstream to alert whenever a certificate is issued for your domains. This catches both shadow IT (teams spinning up *.example.com without approval) and rogue/mis-issued certificates within minutes. This maps to MITRE ATT&CK T1596.001 (Search Open Technical Databases: DNS/Passive DNS) and T1590 (Gather Victim Network Information).

Eliminate dangling DNS records. Subdomain takeover (T1584 — Compromise Infrastructure) is entirely preventable: enforce a deprovisioning workflow that deletes the DNS record before tearing down the cloud resource. Run continuous internal scans (nuclei, subzy) against your own zones so you find the dangling CNAME before a researcher does.

Reduce the discoverable surface. Put internal and staging applications behind a VPN or zero-trust proxy (Cloudflare Access, Tailscale) rather than relying on an unguessable hostname — CT logs make "security through obscurity" worthless. Disable DNS zone transfers (AXFR) to unauthorized hosts; restrict them to your secondary name servers only.

Detect active brute forcing. Authoritative DNS servers and WAFs can flag a flood of NXDOMAIN responses from a single source, the signature of dictionary-based subdomain brute forcing. httpx and ffuf also have recognizable default User-Agent strings and request cadence; rate-limit and challenge anomalous bursts at the edge. Wildcard DNS (*.example.com -> sinkhole) can blunt brute forcing but also hides real misconfigurations, so use it deliberately.

Maintain an authoritative asset inventory. The core defensive gap that recon exploits is that the organization does not know its own attack surface. Run the same toolchain (amass, subfinder, httpx) on a schedule against your own domains, diff the results, and alert on new or changed hosts. Combine it with your runtime app analysis workflow — see intercepting mobile API traffic and Nuclei templating for continuous scanning — so newly discovered hosts are automatically tested.

Conclusion

A disciplined pipeline — passive discovery from CT logs and passive DNS, targeted active brute forcing, dedup, then httpx probing — converts a single root domain into a ranked inventory of live, attackable hosts in minutes. The same workflow is your best defensive tool: the team that enumerates its own surface first, and watches its CT feed continuously, denies attackers the forgotten staging box that becomes an incident. For deeper enrichment once you have live hosts, continue with content discovery and parameter mining covered in directory and parameter fuzzing with ffuf.

References

You Might Also Like

If you found this useful, these related deep-dives cover adjacent techniques and their defenses:

Comments

Copied title and URL