ghostspy
All articles
Recon 2 min read

Continuously Monitor a Bug Bounty/Organisations Attack Surface With One Simple Script

A repeatable, tool-driven workflow for discovering, probing and prioritising internet-facing assets — from subdomain enumeration to templated scanning.

Ghost Spy Updated 9 Jul 2026

External attack surface management (EASM) is, at its core, a data pipeline: discover assets, probe them, enrich the results, and prioritise what matters. This post walks through a workflow I use to map an organisation’s internet-facing footprint with nothing but open-source tools.

Note

Everything here targets example.com. Only run these tools against assets you’re explicitly authorised to test.

The pipeline at a glance

Each stage feeds the next. Discovery widens the set of candidate hosts; probing and enrichment narrow it back down to what’s live and interesting.

flowchart LR
  A[Seed domains] --> B[subfinder]
  B --> C[dnsx]
  C --> D[naabu]
  D --> E[httpx]
  E --> F[nuclei]
  F --> G[Triage & report]

Stage 1 — Discovery

Start wide. Passive subdomain enumeration pulls from certificate transparency logs, public datasets and DNS aggregators without touching the target.

subfinder -d example.com -all -silent > subs.txt
wc -l subs.txt

Resolving what’s real

Not every discovered name resolves. dnsx filters the list down to hosts with live DNS records and captures their addresses.

dnsx -l subs.txt -a -resp -silent > resolved.txt

Stage 2 — Probing

With a resolved set in hand, find the open ports and the live web services.

naabu -l resolved.txt -top-ports 1000 -silent > ports.txt
httpx -l ports.txt -silent -status-code -title -tech-detect > live.txt

Stage 3 — Enrichment and scoring

This is where raw output becomes signal. A small script assigns a crude exposure score so triage starts with the riskiest assets.

import csv

WEIGHTS = {"admin": 5, "api": 3, "staging": 4, "vpn": 4}

def score(host: str) -> int:
    return sum(w for k, w in WEIGHTS.items() if k in host)

with open("live.txt") as f:
    hosts = [line.split()[0] for line in f if line.strip()]

for host in sorted(hosts, key=score, reverse=True):
    print(f"{score(host):>2}  {host}")

Stage 4 — Templated scanning

Finally, run nuclei against the live set. Templated scanning catches known misconfigurations and exposures without hammering the target.

nuclei -l live.txt -severity low,medium,high -silent

Warning

nuclei is active, not passive — it sends real requests. Rate-limit with -rl and scope your templates on production targets to avoid disruption.

Rule of thumb: discovery is cheap, triage is expensive. Invest in scoring so your attention lands on the assets that actually move risk.

Wrapping up

The whole pipeline is scriptable end-to-end, which means it can run on a schedule. That’s the real value of EASM — not a one-off snapshot, but a continuously updated view of what you’re exposing to the internet.

Related articles