Attack surface mapping is building the inventory: every hostname, service, certificate, email domain and third-party dependency that carries your name and is reachable from the internet. You can do it in an afternoon with public data and no scanning of anyone — and the result is the one artefact every other security activity depends on.
Why map passively — and what does “passive” mean here?
Passive mapping reads records that are already public: Certificate Transparency logs, DNS, internet-scan databases, your own pages' headers and HTML. It sends no probes to anyone else's systems and needs no permission beyond owning the domain you're mapping. That matters twice over: it's legal and polite when you're an agency mapping a prospect's surface before a conversation, and it's exactly what an attacker does first — so the map you build is the map they have.
Active steps (port scanning, directory brute-forcing, vulnerability probes) come after the map, only against hosts you own or are authorised to test.
The afternoon walkthrough
1. Hostnames from Certificate Transparency
Every publicly trusted certificate ever issued for your domain is logged and searchable. This one query usually surfaces subdomains nobody on the team remembers:
curl -s "https://crt.sh/?q=%25.example.com&output=json" \
| jq -r '.[].name_value' | tr 'A-Z' 'a-z' | sed 's/\*\.//' | sort -u | tee ct-hosts.txt | wc -lThe Website Security Score shows the same count as a teaser (“N subdomains seen in CT logs”) so you can gauge sprawl before running anything.
2. DNS — what each name points at
# A/AAAA = you (or your host); CNAME = someone else's platform; NXDOMAIN target = dangling → takeover risk
while read h; do
printf "%-40s %-18s %s\n" "$h" "$(dig +short A $h | head -1)" "$(dig +short CNAME $h | head -1)"
done < ct-hosts.txt | tee dns-map.txt
# Zone-level facts for the apex
dig +short MX example.com; dig +short TXT example.com; dig +short TXT _dmarc.example.com; dig +short NS example.comExport the zone from your DNS provider as well — CT only shows names that had certificates; the zone shows everything, including hosts that never had HTTPS (which is its own finding).
3. Ports and services — without scanning
Look your IPs up in Censys or Shodan. Both have already scanned the internet; you are reading their notes, not knocking on doors. Anything other than 80/443 on a web host, or 25/465/587 on a mail host, goes on the reduce list.
4. Technology fingerprint per live host
# Server, framework and CMS hints from headers and HTML — the same signals attackers match to exploits
curl -sI https://www.example.com/ | grep -iE '^(server|x-powered-by|x-generator|via):'
curl -s https://www.example.com/ | grep -ioE '<meta name="generator" content="[^"]+"' | head -15. Certificates — what's expiring, what's odd
for h in $(cat live.txt); do
printf "%-40s %s\n" "$h" "$(echo | openssl s_client -servername $h -connect $h:443 2>/dev/null | openssl x509 -noout -enddate | cut -d= -f2)"
doneWhile you're in CT: search for your brand without the dot — %25example%25 — to see certificates issued for names that merely resemble yours. That is the lookalike surface; it's not yours, but it's aimed at you.
6. Email posture per domain
SPF, DKIM (probe the common selectors) and DMARC for every domain you own, including parked ones. The Email / DMARC checker does this in one pass with plain-English verdicts.
7. Third-party footprint
From the CNAMEs (helpdesk, status page, blog platform, marketing tools) and from the script and image origins your pages reference — the CSP Checker's starter policy lists exactly those origins. Each is code or content you run under your name.
What does the finished map look like?
One table, one row per hostname. The columns are what make it useful a month later:
hostname | ip / cname target | owner | purpose | keep? | tech | score | notes
www.example.com | 203.0.113.10 | web team| main site | keep | Next.js/CF | A |
old.example.com | 203.0.113.11 | ? | 2023 site | RETIRE| WP 6.2 | D | no owner — delete by Oct 1
help.example.com | CNAME acme.zendesk.com | support | helpdesk | keep | SaaS | n/a | third-party; in monitoring
promo.example.com | CNAME pages.oldtool.io | - | - | FIX | - | - | dangling: target NXDOMAIN
mail.example.com | 203.0.113.20 | IT | mail | keep | Postfix | - | ports 25/587 onlyDownload the template: attack-surface-map-template.md (Markdown table, edit anywhere). Keep it in version control; the monthly diff is your change report.
For the site owner and for the developer
For the site owner (plain English)
You want one page that lists every website and subdomain your business has, who owns each one, and whether it should still exist. If nobody can produce that page, that is the first security project — and it costs an afternoon, not a budget. Once it exists, deleting what's on the “retire” rows and switching on monitoring for the rest is most of what “attack surface management” means at your size.
The map covers what you own. The Domain Monitor covers what appears next to it: lookalike certificates, typosquat registrations and cloned copies of your site — free for your verified domain during the beta.
Add monitoring to the map →For the developer / IT
Automate steps 1–2 and 5 as a scheduled job that writes the table and opens a diff for review; leave 3–4 and 7 as monthly manual reads. If you run subfinder/amass, do it in passive mode against your own domains only, and treat every host they find that CT didn't as a “never had HTTPS” finding in its own right. Feed retire/fix rows into the same backlog as bugs; see the reduction checklist for what to do with each.