Vulnerability Hunting
Turn your service and web inventory into a prioritized list of likely vulnerabilities, at scale.
By now you have a full inventory: services with versions, live web apps with
fingerprinted technologies, and discovered content. Hunting is where you work
through that inventory for known weaknesses — fast, broad, and automated first,
then manual verification.
This is identification, not exploitation. The output is a list of probable
findings, each of which you then confirm by hand (see Evidence &
Reporting). Automated scanners produce false
positives, so never report a finding you haven’t reproduced.
The hunting passes
- Automated scanning with nuclei — template-driven checks for
CVEs, misconfigurations, exposures, and default credentials across every web
service at once.
- Known exploits with searchsploit — map your nmap
service versions to public exploits.
- Subdomain takeover — find dangling DNS records
pointing at unclaimed cloud resources.
Order of operations
Run the cheap, broad passes first to triage, then go deep on what they flag:
nuclei (broad) ──┐
searchsploit ────┼──▶ triaged candidate findings ──▶ manual verification ──▶ report
takeover checks ─┘
Then pivot to manual, application-specific testing on the high-value targets the
recon screenshots
surfaced — login panels, admin consoles, APIs. Automation finds the easy 80%; the
findings that actually matter usually come out of the manual 20%.
Stay in scope, stay polite
Hunting is the loudest phase — nuclei alone can fire thousands of requests per
host. Re-read your rules of
engagement:
honor rate limits (nuclei -rl), keep intrusive templates off fragile
production, and never run exploitation modules without explicit authorization.
Start with nuclei.
1 - Automated Scanning with Nuclei
Run template-based vulnerability checks across every web service to surface CVEs, misconfigurations, and exposures fast.
nuclei does most of the heavy
lifting in the hunting phase. It runs a big community library of YAML
templates — each one a precise check for a specific CVE, misconfiguration,
default credential, or information exposure — against your targets. It’s fast,
the false-positive rate is low (each template encodes a real matcher), and the
template set gets updated constantly.
Setup
nuclei -update # update the binary
nuclei -update-templates # pull the latest template library
Run against your live URLs
Feed nuclei the live URL list from HTTP probing.
Use a project file so re-runs don’t repeat work:
nuclei -l recon/live-urls.txt \
-project -project-path .nuclei \
-severity low,medium,high,critical \
-o recon/nuclei-all.txt \
-json-export recon/nuclei-all.json \
-stats
Scan by template category
Arsenic splits nuclei into focused passes — technologies first (to fingerprint
what’s there), then CVEs (to find what’s exploitable). Running targeted
template groups is faster and easier to triage than one giant run:
# Fingerprint technologies / detections
nuclei -l recon/live-urls.txt -project -project-path .nuclei \
-tags tech -o recon/nuclei-technologies.txt
# Known CVEs
nuclei -l recon/live-urls.txt -project -project-path .nuclei \
-tags cve -severity high,critical -o recon/nuclei-cves.txt
# Exposures: panels, config files, backups, secrets
nuclei -l recon/live-urls.txt -project -project-path .nuclei \
-t http/exposures/ -t http/exposed-panels/ -o recon/nuclei-exposures.txt
# Default credentials
nuclei -l recon/live-urls.txt -project -project-path .nuclei \
-t http/default-logins/ -o recon/nuclei-default-logins.txt
Split results back to per-host
To keep findings with their host (Arsenic stores nuclei-cves.txt under each
host’s recon/), partition the output by hostname:
while read -r host; do
grep -F "$host" recon/nuclei-cves.txt > "hosts/$host/recon/nuclei-cves.txt"
[ -s "hosts/$host/recon/nuclei-cves.txt" ] || rm -f "hosts/$host/recon/nuclei-cves.txt"
done < <(ls hosts/)
Be a good guest
-rl 150 — cap requests/second (rate limit) for fragile targets.-c 25 — control concurrency.-exclude-tags intrusive,dos,fuzz — skip templates that can damage or
destabilize a target unless you’re explicitly cleared for them.-proxy http://127.0.0.1:8080 — route through Burp to log and review every
request.
Triage every hit
Nuclei is high-signal but it isn’t infallible. For each result:
- Read the matched template (
nuclei -tl -t <template> shows it). - Reproduce the finding manually —
curl, browser, or Burp. - Only then promote it to a finding.
The template severity is a starting point; the real severity depends on the
asset and the business context. A “medium” exposure on an admin panel can be your
highest-impact finding.
Next: map service versions to public exploits with
searchsploit.
2 - Known Exploits with SearchSploit
Map the service versions you found to public exploits in Exploit-DB.
Your service enumeration produced versioned
services — vsftpd 2.3.4, Apache Tomcat 8.5.32, OpenSSH 7.2. SearchSploit
checks those versions against the offline Exploit-DB
archive, so you can find public exploits without leaving your terminal.
Setup
searchsploit ships with the exploitdb package. Keep the database current:
sudo apt install exploitdb # or: git clone exploitdb to /opt and symlink
searchsploit -u # update the local exploit database
Feed it your nmap results directly
The part I like: searchsploit reads nmap XML and looks up every detected service
automatically. Point it at the version/service scans (not the quick port
sweeps). This is what Arsenic’s as-searchsploit does:
find hosts -name 'nmap-tcp.xml' | while read -r xml; do
echo "[*] $xml"
searchsploit --nmap "$xml" 2>/dev/null | tee "$xml.searchsploit.txt"
done
Manual lookups
For one-off checks:
searchsploit apache tomcat 8.5
searchsploit --cve 2021-44228 # search by CVE
searchsploit -x linux/remote/12345.c # view an exploit
searchsploit -m linux/remote/12345.c # copy it to the cwd to inspect/use
Verify before you trust
Public exploits are a lead, not a finding:
- Match the version precisely. Exploits are version-specific; “close” often
doesn’t fire, and a mismatched exploit can crash the service.
- Read the code before running it. Exploit-DB hosts unvetted PoCs — some are
broken, some are trojaned, some are destructive. Understand what it does first.
- Confirm exploitability in your authorized scope. Running an RCE exploit is
exploitation, not identification — make sure your rules of engagement permit
it, and prefer a benign proof (version banner, safe PoC) where you can.
nuclei -tags cve (previous page) overlaps usefully — it actively tests many
CVEs rather than just matching versions.- Metasploit’s
search and db_import (of your nmap XML) is another route to map
services to modules when you’re cleared to exploit.
Confirmed-exploitable services become findings.
Next, check for subdomain takeover.
3 - Subdomain Takeover
Find dangling DNS records pointing at unclaimed cloud resources you can hijack.
A subdomain takeover happens when a DNS record (usually a CNAME) points at a
third-party service — S3, GitHub Pages, Heroku, Azure, a SaaS app — that’s since
been deleted or never claimed. Anyone who registers that resource controls
content served on the client’s subdomain. It’s high-impact and often overlooked,
and your discovery phase already handed you the full subdomain
list to check.
How to spot one
The signature is a CNAME pointing to an external service that returns a
service-specific “not found / no such bucket / unclaimed” error. For example,
assets.example.com CNAME’d to a non-existent S3 bucket returns NoSuchBucket.
Arsenic originally caught these via aquatone’s takeover tags. The dedicated tools
are more reliable now.
subzy (what I use)
subzy checks a list of subdomains
against a fingerprint database of vulnerable services:
subzy run --targets recon/domains/example.com/subdomains.txt \
--hide_fails --verify_ssl
nuclei takeover templates
nuclei ships a maintained set of takeover detection templates — convenient if
it’s already in your pipeline:
nuclei -l recon/live-urls.txt -t http/takeovers/ -o recon/takeovers.txt
Manual confirmation
Always confirm before reporting — and do not actually claim the resource
unless your rules of engagement explicitly authorize proving the takeover:
# 1. Confirm the dangling CNAME
dig +short CNAME assets.example.com # -> some-bucket.s3.amazonaws.com
# 2. Confirm the target service returns an unclaimed/error fingerprint
curl -sI https://assets.example.com # -> NoSuchBucket / 404 service error
Cross-reference the fingerprint against
can-i-take-over-xyz, which
catalogs which services are takeover-vulnerable and how to verify each safely.
Reporting
A confirmed dangling record is reportable on its own — you don’t need to seize the
resource to prove impact. Document the vulnerable subdomain, the dangling CNAME
target, the service fingerprint, and the standard remediation (remove the stale
DNS record, or reclaim/repoint the resource). Capture evidence per Evidence &
Reporting.