Continuous attack surface monitoring for a single domain.
Tracks subdomain changes, open ports, service versions, web technologies, DNS drift, and WAF posture β every run diffs against the previous one and only prints what changed.
Designed for bug bounty recon, red team asset tracking, and lightweight corporate ASM pipelines where you want a single cron job that tells you when something on a target changes overnight.
| # | Task | How |
|---|---|---|
| 1 | Subdomain discovery (passive + brute-force) | subfinder, amass, dnsx |
| 2 | Open ports + service versions | naabu β nmap -sV |
| 3 | Web server headers | curl -I |
| 4 | Directory brute-force (per subdomain) | ffuf |
| 5 | Full site crawl | gospider |
| 6 | Technology fingerprinting | whatweb |
| 7 | DNS record monitoring (A/AAAA/MX/NS/TXT/CNAME/SOA) | dig |
| 8 | WAF detection (per subdomain) | wafw00f |
Every section compares today's output against yesterday's snapshot and only reports additions ([+]) and removals ([-]). On first run it builds a baseline silently.
# 1. Clone the repo
git clone https://github.com/verygoodsecbadsec/surphaceinyourhand.git
cd surphaceinyourhand
# 2. Install all dependencies (Debian/Ubuntu, Arch, or macOS)
chmod +x install.sh && ./install.sh
# 3. Copy and edit the config (optional)
cp monitor.conf.example monitor.conf
# 4. Run against a target you have permission to test
./monitor.sh example.comResults are written to ~/monitor/<domain>/ and logged to a dated file.
Run once per day at 03:00 AM:
crontab -e0 3 * * * /path/to/monitor.sh example.com >> /var/log/surphaceinyourhand.log 2>&1For multiple targets, one line per domain:
0 2 * * * /path/to/monitor.sh target-one.com
0 3 * * * /path/to/monitor.sh target-two.com
0 4 * * * /path/to/monitor.sh target-three.comAll settings have sensible defaults and can be overridden in a config file or as environment variables.
./monitor.sh -c monitor.conf example.com| Variable | Default | Description |
|---|---|---|
TOP_PORTS |
1000 |
Number of top ports for naabu to scan |
FFUF_THREADS |
30 |
Concurrent threads per ffuf job |
FFUF_RATE |
100 |
Max requests/sec per ffuf job |
CRAWL_DEPTH |
3 |
gospider crawl depth |
SUBDOMAIN_WORDLIST |
~/wordlists/subdomains-top1million-5000.txt |
Wordlist for subdomain brute-force |
DIR_WORDLIST |
~/wordlists/directories-common.txt |
Wordlist for directory brute-force |
WEBHOOK_URL |
(empty) | Slack or Discord webhook URL for change alerts |
Copy monitor.conf.example to monitor.conf and adjust:
TOP_PORTS=3000
FFUF_THREADS=50
FFUF_RATE=150
WEBHOOK_URL="https://hooks.slack.com/services/..."Set WEBHOOK_URL to any Slack-compatible incoming webhook. The script sends a notification only when at least one [+] or [-] change is detected β no noise on quiet nights.
Compatible with: Slack, Discord (use /slack webhook format), and any service accepting a {"text": "..."} POST body.
~/monitor/
βββ example.com/
βββ log_20240915_030001.log # Full timestamped log
βββ previous/ # Yesterday's snapshot (diffed against)
β βββ subs_alive.txt
β βββ ports_open.txt
β βββ versions.txt
β βββ server_headers.txt
β βββ dirs_all.txt
β βββ crawl_paths.txt
β βββ tech_all.txt
β βββ dns_records.txt
β βββ waf_status.txt
βββ previous.bak/ # Two-day-old snapshot (safety net)
The current/ directory is created at the start of each run and atomically rotated to previous/ on success. If the script is interrupted mid-run the incomplete current/ is removed, leaving previous/ intact.
| Tool | Purpose | Install |
|---|---|---|
| subfinder | Passive subdomain enumeration | go install github.com/projectdiscovery/subfinder/v2/cmd/subfinder@latest |
| amass | Passive subdomain enumeration | go install github.com/owasp-amass/amass/v4/...@latest |
| dnsx | DNS resolution + subdomain brute-force | go install github.com/projectdiscovery/dnsx/cmd/dnsx@latest |
| naabu | Fast port scanner | go install github.com/projectdiscovery/naabu/cmd/naabu@latest |
| nmap | Service version detection | apt install nmap |
| ffuf | Directory brute-force | go install github.com/ffuf/ffuf/v2@latest |
| whatweb | Technology fingerprinting | apt install whatweb |
| gospider | Web crawler | go install github.com/jaeles-project/gospider@latest |
| dig | DNS record queries | apt install dnsutils |
| wafw00f | WAF detection | pip3 install wafw00f |
| curl | HTTP header fetching | system package |
| jq | JSON parsing (ffuf output) | apt install jq |
Run ./install.sh to handle all of the above automatically.
The script expects two wordlists:
~/wordlists/subdomains-top1million-5000.txt
~/wordlists/directories-common.txt
install.sh downloads these automatically from SecLists. To use your own, set the paths in monitor.conf.
./monitor.sh [OPTIONS] <domain>
Options:
-c <file> Load config from file (overrides defaults)
--dry-run Print config and exit without running any scans
- Scope: runs against one domain per invocation. Use multiple cron entries for multiple targets.
- Rate limiting: ffuf defaults to 100 req/s. Reduce
FFUF_RATEif the target is sensitive to traffic volume.
This tool is intended for authorized use in CTF competitions, security research, and controlled test environments only. Capturing traffic on networks you do not own or have explicit permission to monitor is illegal in most jurisdictions. The author accepts no liability for unauthorized use.
- This project is licensed under the MIT License β see the LICENSE file for details.