June 23, 2026
Bug Bounty Recon Mastery →Advanced Reconnaissance and Attack Surface Mapping V2
Real-World Deep Dive Advanced Reconnaissance.

By MD Mehedi Hasan
20 min read
In bug bounty hunting, finding vulnerabilities is not only about testing endpoints — it starts with understanding the entire attack surface.
A strong reconnaissance process helps security researchers discover hidden assets, forgotten subdomains, exposed services, cloud resources, historical endpoints, and potential security weaknesses before deeper testing begins.
This guide covers an advanced real-world reconnaissance workflow including certificate analysis, subdomain enumeration, DNS intelligence, OSINT techniques, JavaScript analysis, cloud asset discovery, ASN mapping, and automated attack surface monitoring — all designed for authorized security research and penetration testing.
Part 1: Certificate Analysis & Subdomain Enumeration (Deep Dive)
1.1 TLS Certificate Deep Analysis
From the certificate you provided, let me extract every single piece of intelligence:
Certificate Fingerprint: 35ae3a37dac4f2a3f7dd08d0404c119323ed5fea9c1242d59acc0ce0b29754db
Subject CN: example.com
Issuer CN: WE1 (Google Trust Services)
Valid: May 11, 2026 → August 9, 2026
Public Key: b805ec55647950d1e718ce864d4bec72a96cae8e8feaf730853a45166df264c3Certificate Fingerprint: 35ae3a37dac4f2a3f7dd08d0404c119323ed5fea9c1242d59acc0ce0b29754db
Subject CN: example.com
Issuer CN: WE1 (Google Trust Services)
Valid: May 11, 2026 → August 9, 2026
Public Key: b805ec55647950d1e718ce864d4bec72a96cae8e8feaf730853a45166df264c3Ntelligence Extracted from This Certificate:
-
Certificate Authority Fingerprinting The issuer
WE1is a Google Trust Services intermediate CA. This tells us example.com uses Google Cloud Certificate Authority Service or Google Trust Services' automated certificate issuance. The short 90-day validity suggests ACME automation (likely Certbot or Google's own managed TLS). -
Cloudflare Proxying Confirmed The A records resolve to
162.159.152.4and162.159.153.4— both are Cloudflare edge IPs (AS13335). The certificate presented to clients is a Cloudflare edge certificate, not the origin. This means:
- Origin IPs are hidden behind Cloudflare
- WAF rules apply at the edge
- Direct origin access requires historical DNS records, Shodan, or Censys
- Public Key Fingerprint Analysis The public key hex
b805ec55647950d1e718ce864d4bec72a96cae8e8feaf730853a45166df264c3can be used to:
- Track this certificate across different services
- Identify shared infrastructure
- Detect certificate reuse on other domains
Automated Certificate Analysis Script
#!/bin/bash
# cert_analyze.sh - Deep TLS certificate intelligence gathering
DOMAIN="example.com"
echo "[+] Deep Certificate Analysis for $DOMAIN"
# 1. Fetch full certificate chain
echo "[*] Fetching certificate chain..."
openssl s_client -connect $DOMAIN:443 -servername $DOMAIN -showcerts \
</dev/null 2>/dev/null | openssl x509 -text -noout > cert_full.txt
# 2. Extract SANs (Subject Alternative Names)
echo "[*] Extracting SAN entries..."
openssl s_client -connect $DOMAIN:443 -servername $DOMAIN \
</dev/null 2>/dev/null | openssl x509 -noout -ext subjectAltName
# 3. Extract all fields
openssl s_client -connect $DOMAIN:443 -servername $DOMAIN \
</dev/null 2>/dev/null | openssl x509 -noout \
-subject -issuer -dates -fingerprint -pubkey
# 4. Check certificate transparency via crt.sh
echo "[*] Querying Certificate Transparency logs..."
curl -s "https://crt.sh/?q=%25.$DOMAIN&output=json" | \
jq -r '.[] | "\(.name_value) | \(.not_before) → \(.not_after) | \(.issuer_name)"' \
> ct_logs_full.txt
# 5. Censys.io certificate search (if API key configured)
# curl -s -H "Accept: application/json" \
# "https://search.censys.io/api/v2/certificates/search?q=example.com"
# 6. Check for certificate transparency exclusion (evil bit)
echo "[*] Checking CAA records..."
dig CAA $DOMAIN +short
echo "[+] Done. Full cert chain saved to cert_full.txt"#!/bin/bash
# cert_analyze.sh - Deep TLS certificate intelligence gathering
DOMAIN="example.com"
echo "[+] Deep Certificate Analysis for $DOMAIN"
# 1. Fetch full certificate chain
echo "[*] Fetching certificate chain..."
openssl s_client -connect $DOMAIN:443 -servername $DOMAIN -showcerts \
</dev/null 2>/dev/null | openssl x509 -text -noout > cert_full.txt
# 2. Extract SANs (Subject Alternative Names)
echo "[*] Extracting SAN entries..."
openssl s_client -connect $DOMAIN:443 -servername $DOMAIN \
</dev/null 2>/dev/null | openssl x509 -noout -ext subjectAltName
# 3. Extract all fields
openssl s_client -connect $DOMAIN:443 -servername $DOMAIN \
</dev/null 2>/dev/null | openssl x509 -noout \
-subject -issuer -dates -fingerprint -pubkey
# 4. Check certificate transparency via crt.sh
echo "[*] Querying Certificate Transparency logs..."
curl -s "https://crt.sh/?q=%25.$DOMAIN&output=json" | \
jq -r '.[] | "\(.name_value) | \(.not_before) → \(.not_after) | \(.issuer_name)"' \
> ct_logs_full.txt
# 5. Censys.io certificate search (if API key configured)
# curl -s -H "Accept: application/json" \
# "https://search.censys.io/api/v2/certificates/search?q=example.com"
# 6. Check for certificate transparency exclusion (evil bit)
echo "[*] Checking CAA records..."
dig CAA $DOMAIN +short
echo "[+] Done. Full cert chain saved to cert_full.txt"1.2 Subdomain Enumeration (The Complete Playbook)
Phase A: Certificate Transparency Log Scraping
This is the single most effective passive technique. CT logs are append-only public ledgers of every TLS certificate ever issued. crt.sh indexes them.
# The foundational query - always start here
curl -s "https://crt.sh/?q=%25.example.com&output=json" | \
jq -r '.[].name_value' | \
grep -v '^\*\.' | \
tr '\n' '\n' | sort -u > medium_crtsh.txt# The foundational query - always start here
curl -s "https://crt.sh/?q=%25.example.com&output=json" | \
jq -r '.[].name_value' | \
grep -v '^\*\.' | \
tr '\n' '\n' | sort -u > medium_crtsh.txtWhy this works: Any subdomain that ever had a TLS certificate is in these logs — even subdomains that are no longer in DNS, no longer resolving, or pointing to decommissioned infrastructure. This is how bug bounty hunters find forgotten staging environments, deprecated API endpoints, and vulnerable legacy services.
Phase B: Multi-Engine Passive Aggregation
# 1. Subfinder (40+ passive sources: SecurityTrails, VirusTotal, AlienVault, etc.)
subfinder -d example.com -all -recursive -silent -o medium_subfinder.txt
# 2. Assetfinder (quick passive from crt.sh, ThreatCrowd, etc.)
assetfinder --subs-only example.com > medium_assetfinder.txt
# 3. Amass passive (integrations with 30+ sources)
amass enum -passive -d example.com -o medium_amass.txt
# 4. Findomain (uses SecurityTrails, VirusTotal, etc.)
findomain -t example.com -u medium_findomain.txt
# 5. Sublist3r (uses Google, Yahoo, Bing, Baidu, Ask, Netcraft, DNSDumpster)
sublist3r -d example.com -o medium_sublist3r.txt
# 6. Chaos dataset (ProjectDiscovery's DNS dataset)
chaos -d example.com -silent -o medium_chaos.txt
# 7. Combine all sources
cat example_*.txt | grep -E '\.example\.com$' | sort -u > all_passive_subs.txt
echo "[+] Total unique passive subdomains: $(wc -l < all_passive_subs.txt)"# 1. Subfinder (40+ passive sources: SecurityTrails, VirusTotal, AlienVault, etc.)
subfinder -d example.com -all -recursive -silent -o medium_subfinder.txt
# 2. Assetfinder (quick passive from crt.sh, ThreatCrowd, etc.)
assetfinder --subs-only example.com > medium_assetfinder.txt
# 3. Amass passive (integrations with 30+ sources)
amass enum -passive -d example.com -o medium_amass.txt
# 4. Findomain (uses SecurityTrails, VirusTotal, etc.)
findomain -t example.com -u medium_findomain.txt
# 5. Sublist3r (uses Google, Yahoo, Bing, Baidu, Ask, Netcraft, DNSDumpster)
sublist3r -d example.com -o medium_sublist3r.txt
# 6. Chaos dataset (ProjectDiscovery's DNS dataset)
chaos -d example.com -silent -o medium_chaos.txt
# 7. Combine all sources
cat example_*.txt | grep -E '\.example\.com$' | sort -u > all_passive_subs.txt
echo "[+] Total unique passive subdomains: $(wc -l < all_passive_subs.txt)"Phase C: DNS Bruteforce (Active)
Now we brute-force using massive wordlists:
# Using massdns (blazing fast, asynchronous)
massdns \
-r /usr/share/seclists/Discovery/DNS/dns-JH.txt \
-t A \
-o S \
-w massdns_output.txt \
all_passive_subs.txt
# Extract only resolved entries
grep -E " A " massdns_output.txt | awk '{print $1}' | sed 's/\.$//' > resolved_subs.txt
# Using shuffledns (modern alternative)
shuffledns -d example.com \
-w /usr/share/seclists/Discovery/DNS/subdomains-top1million-20000.txt \
-r resolvers.txt -o shuffledns_results.txt
# Using puredns (wildcard filtering is critical for example.com since it has *.example.com)
puredns bruteforce \
/usr/share/wordlists/SecLists/Discovery/DNS/deepmagic.com-prefixes-top50000.txt \
example.com \
-r resolvers.txt \
--wildcard-batch 1000000 \
-o puredns_results.txt# Using massdns (blazing fast, asynchronous)
massdns \
-r /usr/share/seclists/Discovery/DNS/dns-JH.txt \
-t A \
-o S \
-w massdns_output.txt \
all_passive_subs.txt
# Extract only resolved entries
grep -E " A " massdns_output.txt | awk '{print $1}' | sed 's/\.$//' > resolved_subs.txt
# Using shuffledns (modern alternative)
shuffledns -d example.com \
-w /usr/share/seclists/Discovery/DNS/subdomains-top1million-20000.txt \
-r resolvers.txt -o shuffledns_results.txt
# Using puredns (wildcard filtering is critical for example.com since it has *.example.com)
puredns bruteforce \
/usr/share/wordlists/SecLists/Discovery/DNS/deepmagic.com-prefixes-top50000.txt \
example.com \
-r resolvers.txt \
--wildcard-batch 1000000 \
-o puredns_results.txtCritical Note: *.example.com is a wildcard DNS record. This means any non-existent subdomain will still resolve to Cloudflare. You MUST use tools with wildcard detection (puredns, dnsx with wildcard filtering) or you'll get thousands of false positives.
# Wildcard filtering with dnsx
cat all_possible_subs.txt | dnsx -a -resp -wd example.com -o real_subs.txt# Wildcard filtering with dnsx
cat all_possible_subs.txt | dnsx -a -resp -wd example.com -o real_subs.txtPhase D: Permutation Attack
This is where the real gold is. Using known subdomains, generate mutations:
# Install dnsgen
pip3 install dnsgen
# Generate permutations from known subdomains
cat real_subs.txt | dnsgen - \
-w /usr/share/seclists/Discovery/DNS/permutations_list.txt \
> permutations.txt
# Resolve the permutations
cat permutations.txt | massdns -r resolvers.txt -t A -o S | \
grep -E " A " | awk '{print $1}' | sed 's/\.$//' > new_discovered.txt# Install dnsgen
pip3 install dnsgen
# Generate permutations from known subdomains
cat real_subs.txt | dnsgen - \
-w /usr/share/seclists/Discovery/DNS/permutations_list.txt \
> permutations.txt
# Resolve the permutations
cat permutations.txt | massdns -r resolvers.txt -t A -o S | \
grep -E " A " | awk '{print $1}' | sed 's/\.$//' > new_discovered.txtPermutation patterns applied to example.com:
Known: api.example.com
Permutations:
api-v1.example.com, api-v2.example.com, v1-api.example.com
api-dev.example.com, dev-api.example.com, api-staging.example.com
api-internal.example.com, api-admin.example.com
api-backup.example.com, api-old.example.com, api-beta.example.com
Known: cdn-images-1.example.com
Permutations:
cdn-images-3.example.com, cdn-images-4.example.com
cdn-images-prod.example.com, cdn-images-dev.example.com
cdn-images-internal.example.com
images-1.example.com, images-cdn-1.example.com
Known: help.example.com
Permutations:
help-dev.example.com, help-staging.example.com
zendesk.example.com, support.example.com
helpdesk.example.com, ticket.example.comKnown: api.example.com
Permutations:
api-v1.example.com, api-v2.example.com, v1-api.example.com
api-dev.example.com, dev-api.example.com, api-staging.example.com
api-internal.example.com, api-admin.example.com
api-backup.example.com, api-old.example.com, api-beta.example.com
Known: cdn-images-1.example.com
Permutations:
cdn-images-3.example.com, cdn-images-4.example.com
cdn-images-prod.example.com, cdn-images-dev.example.com
cdn-images-internal.example.com
images-1.example.com, images-cdn-1.example.com
Known: help.example.com
Permutations:
help-dev.example.com, help-staging.example.com
zendesk.example.com, support.example.com
helpdesk.example.com, ticket.example.comPhase E: TLS Certificate Enumeration (Beyond crt.sh)
# Search by Issuer CA
curl -s "https://crt.sh/?iCAID=286236&output=json" | \
jq -r '.[].name_value' | grep -E 'example\.com$' | sort -u
# Search by SHA-256 fingerprint of public key (find shared hosting)
curl -s "https://crt.sh/?spkisha256=b805ec55647950d1e718ce864d4bec72a96cae8e8feaf730853a45166df264c3&output=json" | \
jq -r '.[].name_value' | sort -u
# Search by serial number
curl -s "https://crt.sh/?serial=219b3bec3c9b612813981e7d979a4db7&output=json"
# Censys Certificate Search
# https://search.censys.io/certificates?q=example.com# Search by Issuer CA
curl -s "https://crt.sh/?iCAID=286236&output=json" | \
jq -r '.[].name_value' | grep -E 'example\.com$' | sort -u
# Search by SHA-256 fingerprint of public key (find shared hosting)
curl -s "https://crt.sh/?spkisha256=b805ec55647950d1e718ce864d4bec72a96cae8e8feaf730853a45166df264c3&output=json" | \
jq -r '.[].name_value' | sort -u
# Search by serial number
curl -s "https://crt.sh/?serial=219b3bec3c9b612813981e7d979a4db7&output=json"
# Censys Certificate Search
# https://search.censys.io/certificates?q=example.com1.3 CSP Enumeration (Content Security Policy)
CSP headers often leak subdomains, CDN origins, and API endpoints:
# Extract CSP from live subdomains
while read sub; do
echo "[*] Checking $sub"
curl -s -I "https://$sub" 2>/dev/null | \
grep -i "content-security-policy" | \
sed 's/content-security-policy: //I'
done < live_subs.txt
# Automated with httpx
cat live_subs.txt | httpx -csp-probe -silent | grep -oP "https?://[a-zA-Z0-9.-]*\.example\.com" | sort -u# Extract CSP from live subdomains
while read sub; do
echo "[*] Checking $sub"
curl -s -I "https://$sub" 2>/dev/null | \
grep -i "content-security-policy" | \
sed 's/content-security-policy: //I'
done < live_subs.txt
# Automated with httpx
cat live_subs.txt | httpx -csp-probe -silent | grep -oP "https?://[a-zA-Z0-9.-]*\.example\.com" | sort -uExample CSP analysis for example.com:
Content-Security-Policy:
default-src 'self';
script-src 'self' cdn-client.example.com cdn-static-1.example.com *.cloudflare.com;
img-src 'self' cdn-images-1.example.com cdn-images-2.example.com miro.example.com *.gravatar.com;
connect-src 'self' api.example.com *.sentry.io;
frame-src 'self' example.com *.example.comContent-Security-Policy:
default-src 'self';
script-src 'self' cdn-client.example.com cdn-static-1.example.com *.cloudflare.com;
img-src 'self' cdn-images-1.example.com cdn-images-2.example.com miro.example.com *.gravatar.com;
connect-src 'self' api.example.com *.sentry.io;
frame-src 'self' example.com *.example.comFrom CSP alone, we discover: cdn-client, cdn-static-1, cdn-images-1, cdn-images-2, miro, api — all as confirmed allowed origins.
Part 2: ASN Enumeration
2.1 Finding example.com's ASN
# Find ASN from IP
whois -h whois.cymru.com " -c 162.159.152.4"
# Output: AS13335 | CLOUDFLARENET
# Using BGPView API
curl -s "https://bgpview.io/api/v1/ip/162.159.152.4" | jq
# Using Hurricane Electric
curl -s "https://bgp.he.net/ip/162.159.152.4" | \
grep -oP 'AS[0-9]+' | head -1
# Amass can also pull ASN info
amass intel -org "example" -asn 13335# Find ASN from IP
whois -h whois.cymru.com " -c 162.159.152.4"
# Output: AS13335 | CLOUDFLARENET
# Using BGPView API
curl -s "https://bgpview.io/api/v1/ip/162.159.152.4" | jq
# Using Hurricane Electric
curl -s "https://bgp.he.net/ip/162.159.152.4" | \
grep -oP 'AS[0-9]+' | head -1
# Amass can also pull ASN info
amass intel -org "example" -asn 133352.2 Enumerating All Assets Under the Same ASN
This is crucial — finding other domains and services sharing the same infrastructure:
# Find all IP ranges for AS13335
whois -h whois.radb.net -- '-i origin AS13335' | \
grep -oP '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/[0-9]+' > cloudflare_ranges.txt
# Find all domains hosted on the same IP
curl -s "https://reverse-ip.whoisxmlapi.com/api/v1?apiKey=YOUR_KEY&ip=162.159.152.4"
# Using Shodan
shodan search "ssl.cert.subject.cn:example.com" --fields ip_str,port,org,hostnames
# Using Censys IPv4
# https://search.censys.io/hosts/162.159.152.4
# Amass ASN mapping
amass intel -asn 13335 -max-dns-queries 1000 -o asn_13335_domains.txt# Find all IP ranges for AS13335
whois -h whois.radb.net -- '-i origin AS13335' | \
grep -oP '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/[0-9]+' > cloudflare_ranges.txt
# Find all domains hosted on the same IP
curl -s "https://reverse-ip.whoisxmlapi.com/api/v1?apiKey=YOUR_KEY&ip=162.159.152.4"
# Using Shodan
shodan search "ssl.cert.subject.cn:example.com" --fields ip_str,port,org,hostnames
# Using Censys IPv4
# https://search.censys.io/hosts/162.159.152.4
# Amass ASN mapping
amass intel -asn 13335 -max-dns-queries 1000 -o asn_13335_domains.txtKey Finding: example.com runs on Cloudflare's global network (AS13335). This means:
- All example.com assets share the same CDN infrastructure
- Origin server IPs are hidden
- Any vulnerability in Cloudflare's edge could affect all subdomains
- The attack surface includes Cloudflare's own configuration missteps (e.g., origin IP exposure via DNS history, misconfigured WAF rules)
2.3 Finding the Real Origin IPs (Cloudflare Bypass)
# Method 1: Historical DNS records
# SecurityTrails historical DNS
curl -s "https://api.securitytrails.com/v1/history/example.com/dns/a" \
-H "APIKEY: YOUR_KEY" | jq '.records[].values[].ip'
# Method 2: Certificate Transparency on origin
# Sometimes certificates issued before Cloudflare migration reveal origin IPs
curl -s "https://crt.sh/?q=example.com&output=json&exclude=expired" | \
jq -r '.[].name_value' | sort -u | head -20
# Method 3: Shodan search for example.com SSL certificate
shodan search "ssl.cert.subject.cn:example.com -cloudflare" --fields ip_str
# Method 4: DNS brute-force with direct-to-origin headers
# Send requests with specific Host headers to Cloudflare IPs
curl -H "Host: example.com" https://<origin-ip-candidate>
# Method 5: Check for non-proxied subdomains (gray cloud in Cloudflare)
# Mail subdomains often bypass Cloudflare proxy
dig +short url2204.mail.example.com
# Method 6: F5 / LTM DNS discovery
dig +short example.com @<dns-server># Method 1: Historical DNS records
# SecurityTrails historical DNS
curl -s "https://api.securitytrails.com/v1/history/example.com/dns/a" \
-H "APIKEY: YOUR_KEY" | jq '.records[].values[].ip'
# Method 2: Certificate Transparency on origin
# Sometimes certificates issued before Cloudflare migration reveal origin IPs
curl -s "https://crt.sh/?q=example.com&output=json&exclude=expired" | \
jq -r '.[].name_value' | sort -u | head -20
# Method 3: Shodan search for example.com SSL certificate
shodan search "ssl.cert.subject.cn:example.com -cloudflare" --fields ip_str
# Method 4: DNS brute-force with direct-to-origin headers
# Send requests with specific Host headers to Cloudflare IPs
curl -H "Host: example.com" https://<origin-ip-candidate>
# Method 5: Check for non-proxied subdomains (gray cloud in Cloudflare)
# Mail subdomains often bypass Cloudflare proxy
dig +short url2204.mail.example.com
# Method 6: F5 / LTM DNS discovery
dig +short example.com @<dns-server>Part 3: GitHub Enumeration
3.1 Automated GitHub Reconnaissance
#!/bin/bash
# github_recon.sh - GitHub enumeration for example.com
TARGET="example.com"
OUTPUT_DIR="./github_recon_medium"
mkdir -p $OUTPUT_DIR
# 1. GitHub code search via API
echo "[*] Searching GitHub for '$TARGET' references..."
curl -s -H "Authorization: token YOUR_GITHUB_TOKEN" \
"https://api.github.com/search/code?q=$TARGET&per_page=100" > $OUTPUT_DIR/code_search.json
# 2. Search for API keys and secrets
echo "[*] Searching for potential secrets..."
declare -a SECRET_PATTERNS=(
"example.*api.*key"
"example.*secret"
"example.*token"
"example.*password"
"example.*credentials"
"AKIA[0-9A-Z]{16}" # AWS keys
"sk_live_" # Stripe live keys
"pk_live_"
"ghp_" # GitHub tokens
"xox[bpsa]-" # Slack tokens
)
for pattern in "${SECRET_PATTERNS[@]}"; do
curl -s -H "Authorization: token YOUR_GITHUB_TOKEN" \
"https://api.github.com/search/code?q=$pattern+$TARGET&per_page=50" \
| jq '.items[] | {repo: .repository.full_name, path: .path, url: .html_url}' \
>> $OUTPUT_DIR/secrets.json
done
# 3. Search for internal URLs
echo "[*] Searching for internal example.com URLs..."
curl -s -H "Authorization: token YOUR_GITHUB_TOKEN" \
"https://api.github.com/search/code?q=%22medium.com%22+AND+(staging+OR+dev+OR+internal+OR+admin+OR+vpn)" \
> $OUTPUT_DIR/internal_urls.json
# 4. Search for configuration files
echo "[*] Searching for config files..."
declare -a CONFIG_FILES=(".env" "config.json" "config.yml" ".gitignore" "docker-compose.yml" "Makefile" "terraform.tfvars")
for file in "${CONFIG_FILES[@]}"; do
curl -s -H "Authorization: token YOUR_GITHUB_TOKEN" \
"https://api.github.com/search/code?q=$TARGET+filename:$file" \
| jq '.items[] | {repo: .repository.full_name, path: .path}' \
>> $OUTPUT_DIR/config_files.json
done
echo "[+] GitHub recon complete. Check $OUTPUT_DIR/"#!/bin/bash
# github_recon.sh - GitHub enumeration for example.com
TARGET="example.com"
OUTPUT_DIR="./github_recon_medium"
mkdir -p $OUTPUT_DIR
# 1. GitHub code search via API
echo "[*] Searching GitHub for '$TARGET' references..."
curl -s -H "Authorization: token YOUR_GITHUB_TOKEN" \
"https://api.github.com/search/code?q=$TARGET&per_page=100" > $OUTPUT_DIR/code_search.json
# 2. Search for API keys and secrets
echo "[*] Searching for potential secrets..."
declare -a SECRET_PATTERNS=(
"example.*api.*key"
"example.*secret"
"example.*token"
"example.*password"
"example.*credentials"
"AKIA[0-9A-Z]{16}" # AWS keys
"sk_live_" # Stripe live keys
"pk_live_"
"ghp_" # GitHub tokens
"xox[bpsa]-" # Slack tokens
)
for pattern in "${SECRET_PATTERNS[@]}"; do
curl -s -H "Authorization: token YOUR_GITHUB_TOKEN" \
"https://api.github.com/search/code?q=$pattern+$TARGET&per_page=50" \
| jq '.items[] | {repo: .repository.full_name, path: .path, url: .html_url}' \
>> $OUTPUT_DIR/secrets.json
done
# 3. Search for internal URLs
echo "[*] Searching for internal example.com URLs..."
curl -s -H "Authorization: token YOUR_GITHUB_TOKEN" \
"https://api.github.com/search/code?q=%22medium.com%22+AND+(staging+OR+dev+OR+internal+OR+admin+OR+vpn)" \
> $OUTPUT_DIR/internal_urls.json
# 4. Search for configuration files
echo "[*] Searching for config files..."
declare -a CONFIG_FILES=(".env" "config.json" "config.yml" ".gitignore" "docker-compose.yml" "Makefile" "terraform.tfvars")
for file in "${CONFIG_FILES[@]}"; do
curl -s -H "Authorization: token YOUR_GITHUB_TOKEN" \
"https://api.github.com/search/code?q=$TARGET+filename:$file" \
| jq '.items[] | {repo: .repository.full_name, path: .path}' \
>> $OUTPUT_DIR/config_files.json
done
echo "[+] GitHub recon complete. Check $OUTPUT_DIR/"3.2 Manual GitHub Dorking (Advanced)
# Direct string searches
"example.com" API key
"example.com" password
"example.com" secret
"example.com" .env
"example.com" internal
"example.com" staging
"example.com" "access_key"
"example.com" "BEGIN RSA PRIVATE KEY"
"example.com" "BEGIN OPENSSH PRIVATE KEY"
"example.com" "aws_access_key_id"
"example.com" "db_password"
"example.com" "jdbc:mysql://"
# File-specific searches
"example.com" filename:.env
"example.com" filename:credentials.json
"example.com" filename:config.php
"example.com" filename:database.yml
"example.com" filename:terraform.tfvars
"example.com" filename:Dockerfile
"example.com" filename:Kubeconfig
"example.com" filename:secrets.yml
# Employee-specific
"@example.com" email
"@example.com" password
"@example.com" "git config"
"example.com" "ssh-rsa"# Direct string searches
"example.com" API key
"example.com" password
"example.com" secret
"example.com" .env
"example.com" internal
"example.com" staging
"example.com" "access_key"
"example.com" "BEGIN RSA PRIVATE KEY"
"example.com" "BEGIN OPENSSH PRIVATE KEY"
"example.com" "aws_access_key_id"
"example.com" "db_password"
"example.com" "jdbc:mysql://"
# File-specific searches
"example.com" filename:.env
"example.com" filename:credentials.json
"example.com" filename:config.php
"example.com" filename:database.yml
"example.com" filename:terraform.tfvars
"example.com" filename:Dockerfile
"example.com" filename:Kubeconfig
"example.com" filename:secrets.yml
# Employee-specific
"@example.com" email
"@example.com" password
"@example.com" "git config"
"example.com" "ssh-rsa"3.3 GitHub Commit History Enumeration
Sometimes secrets are removed from files but remain in git history:
# Search commits for example.com references
curl -s -H "Authorization: token YOUR_GITHUB_TOKEN" \
"https://api.github.com/search/commits?q=example.com" | jq '.items[] | {repo: .repository.full_name, message: .commit.message, date: .commit.committer.date}'
# Search commit diffs for added secrets
# Use git-trufflehog or ggshield for deeper analysis# Search commits for example.com references
curl -s -H "Authorization: token YOUR_GITHUB_TOKEN" \
"https://api.github.com/search/commits?q=example.com" | jq '.items[] | {repo: .repository.full_name, message: .commit.message, date: .commit.committer.date}'
# Search commit diffs for added secrets
# Use git-trufflehog or ggshield for deeper analysis3.4 GitHub Organization Enumeration
# Find example.com employees' GitHub accounts
# Common patterns: firstname-lastname, firstname.lastname, flastname
curl -s "https://api.github.com/orgs/example/public_members" | jq '.[].login'# Find example.com employees' GitHub accounts
# Common patterns: firstname-lastname, firstname.lastname, flastname
curl -s "https://api.github.com/orgs/example/public_members" | jq '.[].login'Part 4: Historical Data Sources
4.1 Wayback Machine (archive.org)
This is arguably the most powerful historical source:
#!/bin/bash
# historical_recon.sh - Historical data extraction
TARGET="example.com"
OUTPUT_DIR="./historical_medium"
mkdir -p $OUTPUT_DIR
# 1. Get all known URLs via gau (getallurls)
echo "[*] Fetching all known URLs from Wayback, AlienVault, etc..."
echo $TARGET | gau --subs --providers wayback,commoncrawl,otx,urlscan > $OUTPUT_DIR/all_urls.txt
wc -l $OUTPUT_DIR/all_urls.txt
# 2. Wayback Machine CDX API directly
echo "[*] Fetching historical snapshots..."
curl -s "http://web.archive.org/cdx/search/cdx?url=*.example.com/*&output=json&fl=original,timestamp,statuscode&limit=50000" \
> $OUTPUT_DIR/wayback_cdx.json
# 3. Extract JavaScript files (hidden API endpoints live here)
echo "[*] Extracting JS files..."
grep -E '\.js(\?|$)' $OUTPUT_DIR/all_urls.txt | sort -u > $OUTPUT_DIR/js_files.txt
# 4. Extract API endpoints
echo "[*] Extracting API endpoints..."
grep -iE '(api|graphql|rest|v1|v2|v3|endpoint|internal)' $OUTPUT_DIR/all_urls.txt \
> $OUTPUT_DIR/api_endpoints.txt
# 5. Extract parameters for fuzzing
echo "[*] Extracting URL parameters..."
grep -oP '\?[^ ]+' $OUTPUT_DIR/all_urls.txt | \
sed 's/\?//' | tr '&' '\n' | cut -d'=' -f1 | sort -u \
> $OUTPUT_DIR/parameters.txt
# 6. Find deleted/removed pages (often vulnerabilities)
echo "[*] Finding 404s that used to exist..."
curl -s "http://web.archive.org/cdx/search/cdx?url=example.com/*&output=json&fl=original,statuscode" | \
grep -E "200" | awk '{print $1}' | sort -u > $OUTPUT_DIR/live_in_wayback.txt
echo "[+] Historical recon complete."#!/bin/bash
# historical_recon.sh - Historical data extraction
TARGET="example.com"
OUTPUT_DIR="./historical_medium"
mkdir -p $OUTPUT_DIR
# 1. Get all known URLs via gau (getallurls)
echo "[*] Fetching all known URLs from Wayback, AlienVault, etc..."
echo $TARGET | gau --subs --providers wayback,commoncrawl,otx,urlscan > $OUTPUT_DIR/all_urls.txt
wc -l $OUTPUT_DIR/all_urls.txt
# 2. Wayback Machine CDX API directly
echo "[*] Fetching historical snapshots..."
curl -s "http://web.archive.org/cdx/search/cdx?url=*.example.com/*&output=json&fl=original,timestamp,statuscode&limit=50000" \
> $OUTPUT_DIR/wayback_cdx.json
# 3. Extract JavaScript files (hidden API endpoints live here)
echo "[*] Extracting JS files..."
grep -E '\.js(\?|$)' $OUTPUT_DIR/all_urls.txt | sort -u > $OUTPUT_DIR/js_files.txt
# 4. Extract API endpoints
echo "[*] Extracting API endpoints..."
grep -iE '(api|graphql|rest|v1|v2|v3|endpoint|internal)' $OUTPUT_DIR/all_urls.txt \
> $OUTPUT_DIR/api_endpoints.txt
# 5. Extract parameters for fuzzing
echo "[*] Extracting URL parameters..."
grep -oP '\?[^ ]+' $OUTPUT_DIR/all_urls.txt | \
sed 's/\?//' | tr '&' '\n' | cut -d'=' -f1 | sort -u \
> $OUTPUT_DIR/parameters.txt
# 6. Find deleted/removed pages (often vulnerabilities)
echo "[*] Finding 404s that used to exist..."
curl -s "http://web.archive.org/cdx/search/cdx?url=example.com/*&output=json&fl=original,statuscode" | \
grep -E "200" | awk '{print $1}' | sort -u > $OUTPUT_DIR/live_in_wayback.txt
echo "[+] Historical recon complete."4.2 JavaScript Source Code Analysis
# Download all JS files
mkdir -p $OUTPUT_DIR/js_downloads
while read js_url; do
wget -q "$js_url" -O "$OUTPUT_DIR/js_downloads/$(echo $js_url | md5sum | cut -d' ' -f1).js"
done < $OUTPUT_DIR/js_files.txt
# Extract endpoints from JS (LinkFinder)
linkfinder.py -i $OUTPUT_DIR/js_downloads/ -o $OUTPUT_DIR/js_endpoints.json
# Extract secrets from JS (JSluice)
cat $OUTPUT_DIR/js_downloads/*.js | jsluice -r > $OUTPUT_DIR/js_secrets.json
# Extract hardcoded strings
cat $OUTPUT_DIR/js_downloads/*.js | \
grep -oP '"(https?://[a-zA-Z0-9./_-]+)"' | \
sort -u > $OUTPUT_DIR/js_hardcoded_urls.txt
# Extract API routes (Katana)
katana -list $OUTPUT_DIR/js_files.txt -jc -o $OUTPUT_DIR/katana_output.txt
# Extract with SecretFinder
python3 SecretFinder.py -i $OUTPUT_DIR/js_downloads/*.js -o $OUTPUT_DIR/all_secrets.txt# Download all JS files
mkdir -p $OUTPUT_DIR/js_downloads
while read js_url; do
wget -q "$js_url" -O "$OUTPUT_DIR/js_downloads/$(echo $js_url | md5sum | cut -d' ' -f1).js"
done < $OUTPUT_DIR/js_files.txt
# Extract endpoints from JS (LinkFinder)
linkfinder.py -i $OUTPUT_DIR/js_downloads/ -o $OUTPUT_DIR/js_endpoints.json
# Extract secrets from JS (JSluice)
cat $OUTPUT_DIR/js_downloads/*.js | jsluice -r > $OUTPUT_DIR/js_secrets.json
# Extract hardcoded strings
cat $OUTPUT_DIR/js_downloads/*.js | \
grep -oP '"(https?://[a-zA-Z0-9./_-]+)"' | \
sort -u > $OUTPUT_DIR/js_hardcoded_urls.txt
# Extract API routes (Katana)
katana -list $OUTPUT_DIR/js_files.txt -jc -o $OUTPUT_DIR/katana_output.txt
# Extract with SecretFinder
python3 SecretFinder.py -i $OUTPUT_DIR/js_downloads/*.js -o $OUTPUT_DIR/all_secrets.txt4.3 DNS History Analysis
# SecurityTrails DNS History
curl -s "https://api.securitytrails.com/v1/history/example.com/dns/a" \
-H "APIKEY: YOUR_KEY" | jq -r '.records[] | "\(.first_seen) → \(.last_seen): \(.values[].ip)"' \
> dns_history.txt
# PassiveTotal DNS History
# curl -s "https://api.passivetotal.org/v2/dns/passive/unique?query=example.com" \
# -u "USER:PASS" | jq
# ViewDNS.info
# https://viewdns.info/iphistory/?domain=example.com# SecurityTrails DNS History
curl -s "https://api.securitytrails.com/v1/history/example.com/dns/a" \
-H "APIKEY: YOUR_KEY" | jq -r '.records[] | "\(.first_seen) → \(.last_seen): \(.values[].ip)"' \
> dns_history.txt
# PassiveTotal DNS History
# curl -s "https://api.passivetotal.org/v2/dns/passive/unique?query=example.com" \
# -u "USER:PASS" | jq
# ViewDNS.info
# https://viewdns.info/iphistory/?domain=example.comPart 5: Cloud Asset Enumeration
5.1 AWS S3 Bucket Discovery
#!/bin/bash
# cloud_enum.sh - Cloud asset discovery
TARGET="example"
OUTPUT_DIR="./cloud_assets"
mkdir -p $OUTPUT_DIR
# Common bucket naming patterns
declare -a BUCKET_PATTERNS=(
"$TARGET"
"$TARGET-assets"
"$TARGET-static"
"$TARGET-uploads"
"$TARGET-media"
"$TARGET-backup"
"$TARGET-logs"
"$TARGET-cdn"
"$TARGET-images"
"$TARGET-data"
"$TARGET-prod"
"$TARGET-staging"
"$TARGET-dev"
"$TARGET-docs"
"$TARGET-config"
"assets.$TARGET"
"static.$TARGET"
"media.$TARGET"
"cdn.$TARGET"
"uploads.$TARGET"
"$TARGET-backups"
"www.$TARGET"
"api.$TARGET"
"blog.$TARGET"
"$TARGET-files"
"$TARGET-resources"
)
# Check each bucket
echo "[*] Checking AWS S3 buckets..."
for bucket in "${BUCKET_PATTERNS[@]}"; do
# Check if bucket exists
status=$(curl -s -o /dev/null -w "%{http_code}" "https://$bucket.s3.amazonaws.com")
if [ "$status" != "404" ] && [ "$status" != "403" ]; then
echo "[!] FOUND: $bucket.s3.amazonaws.com (HTTP $status)"
echo "$bucket" >> $OUTPUT_DIR/s3_buckets.txt
fi
# Check if bucket is listable
list_status=$(curl -s -o /dev/null -w "%{http_code}" "https://$bucket.s3.amazonaws.com/?max-keys=1")
if [ "$list_status" == "200" ]; then
echo "[!!!] PUBLIC LISTING: $bucket.s3.amazonaws.com"
echo "$bucket (PUBLIC)" >> $OUTPUT_DIR/s3_public.txt
fi
done
# Using S3Scanner
python3 s3scanner.py --bucket-file $OUTPUT_DIR/s3_buckets.txt --dump
# Using cloud_enum
python3 cloud_enum.py -k "$TARGET" -k "example" -k "example.com"#!/bin/bash
# cloud_enum.sh - Cloud asset discovery
TARGET="example"
OUTPUT_DIR="./cloud_assets"
mkdir -p $OUTPUT_DIR
# Common bucket naming patterns
declare -a BUCKET_PATTERNS=(
"$TARGET"
"$TARGET-assets"
"$TARGET-static"
"$TARGET-uploads"
"$TARGET-media"
"$TARGET-backup"
"$TARGET-logs"
"$TARGET-cdn"
"$TARGET-images"
"$TARGET-data"
"$TARGET-prod"
"$TARGET-staging"
"$TARGET-dev"
"$TARGET-docs"
"$TARGET-config"
"assets.$TARGET"
"static.$TARGET"
"media.$TARGET"
"cdn.$TARGET"
"uploads.$TARGET"
"$TARGET-backups"
"www.$TARGET"
"api.$TARGET"
"blog.$TARGET"
"$TARGET-files"
"$TARGET-resources"
)
# Check each bucket
echo "[*] Checking AWS S3 buckets..."
for bucket in "${BUCKET_PATTERNS[@]}"; do
# Check if bucket exists
status=$(curl -s -o /dev/null -w "%{http_code}" "https://$bucket.s3.amazonaws.com")
if [ "$status" != "404" ] && [ "$status" != "403" ]; then
echo "[!] FOUND: $bucket.s3.amazonaws.com (HTTP $status)"
echo "$bucket" >> $OUTPUT_DIR/s3_buckets.txt
fi
# Check if bucket is listable
list_status=$(curl -s -o /dev/null -w "%{http_code}" "https://$bucket.s3.amazonaws.com/?max-keys=1")
if [ "$list_status" == "200" ]; then
echo "[!!!] PUBLIC LISTING: $bucket.s3.amazonaws.com"
echo "$bucket (PUBLIC)" >> $OUTPUT_DIR/s3_public.txt
fi
done
# Using S3Scanner
python3 s3scanner.py --bucket-file $OUTPUT_DIR/s3_buckets.txt --dump
# Using cloud_enum
python3 cloud_enum.py -k "$TARGET" -k "example" -k "example.com"5.2 Google Cloud Storage Buckets
# Check GCP buckets
declare -a GCP_PATTERNS=(
"$TARGET"
"$TARGET-assets"
"$TARGET-static"
"$TARGET-uploads"
"$TARGET-media"
"$TARGET-backup"
)
for bucket in "${GCP_PATTERNS[@]}"; do
# Check GCS
status=$(curl -s -o /dev/null -w "%{http_code}" "https://storage.googleapis.com/$bucket/")
if [ "$status" != "404" ]; then
echo "[!] GCP Bucket: $bucket"
fi
done# Check GCP buckets
declare -a GCP_PATTERNS=(
"$TARGET"
"$TARGET-assets"
"$TARGET-static"
"$TARGET-uploads"
"$TARGET-media"
"$TARGET-backup"
)
for bucket in "${GCP_PATTERNS[@]}"; do
# Check GCS
status=$(curl -s -o /dev/null -w "%{http_code}" "https://storage.googleapis.com/$bucket/")
if [ "$status" != "404" ]; then
echo "[!] GCP Bucket: $bucket"
fi
done5.3 Azure Storage Discovery
# Check Azure blobs
declare -a AZURE_PATTERNS=(
"$TARGET"
"$TARGET-assets"
"$TARGET-static"
)
for blob in "${AZURE_PATTERNS[@]}"; do
status=$(curl -s -o /dev/null -w "%{http_code}" "https://${blob}.blob.core.windows.net/")
if [ "$status" != "404" ]; then
echo "[!] Azure Blob: $blob"
fi
done# Check Azure blobs
declare -a AZURE_PATTERNS=(
"$TARGET"
"$TARGET-assets"
"$TARGET-static"
)
for blob in "${AZURE_PATTERNS[@]}"; do
status=$(curl -s -o /dev/null -w "%{http_code}" "https://${blob}.blob.core.windows.net/")
if [ "$status" != "404" ]; then
echo "[!] Azure Blob: $blob"
fi
done5.4 DigitalOcean Spaces & Other Providers
# DigitalOcean Spaces
for space in "${BUCKET_PATTERNS[@]}"; do
curl -s -o /dev/null -w "%{http_code}" "https://${space}.nyc3.digitaloceanspaces.com/"
done# DigitalOcean Spaces
for space in "${BUCKET_PATTERNS[@]}"; do
curl -s -o /dev/null -w "%{http_code}" "https://${space}.nyc3.digitaloceanspaces.com/"
donePart 6: Permutation Attack (Advanced)
6.1 DNS Permutation Engine
Building on the subdomain enumeration, this is where we generate every possible variation:
#!/bin/bash
# permutation_engine.sh - Smart DNS permutation attack
TARGET="example.com"
KNOWN_SUBS=$(cat real_subs.txt)
# Common prefixes and suffixes
PREFIXES=(
"dev" "staging" "prod" "test" "beta" "alpha" "demo" "sandbox"
"internal" "external" "private" "public" "secure" "admin"
"management" "dashboard" "portal" "console" "monitor" "metrics"
"logs" "audit" "backup" "replica" "mirror" "cdn" "origin"
"assets" "static" "media" "images" "videos" "files"
"api" "rest" "graphql" "soap" "webhook" "websocket"
"mail" "smtp" "pop3" "imap" "exchange"
"vpn" "proxy" "gateway" "bastion" "jump"
"jenkins" "gitlab" "jira" "confluence" "wiki"
"kibana" "grafana" "prometheus" "nagios" "splunk"
"docker" "k8s" "kubernetes" "cluster" "node"
"us" "eu" "asia" "apac" "emea" "amer"
"us-east" "us-west" "eu-west" "eu-central" "ap-southeast"
"1" "01" "001" "2" "02" "002" "3" "03" "003"
"old" "new" "current" "previous" "legacy"
"v1" "v2" "v3" "version1" "version2"
"app" "web" "mobile" "ios" "android"
"auth" "login" "sso" "oauth" "identity"
"payment" "billing" "checkout" "cart"
"search" "discover" "explore" "trending"
"notifications" "push" "sms" "email"
"docs" "documentation" "help" "support" "faq"
)
SUFFIXES=(
"-dev" "-staging" "-prod" "-test" "-beta" "-old" "-new" "-backup"
"-internal" "-external" "-private" "-public" "-secure" "-admin"
"-api" "-ui" "-svc" "-service" "-app" "-web" "-site"
"-cdn" "-origin" "-proxy" "-gw" "-gateway"
"-us" "-eu" "-asia" "-1" "-2" "-01" "-02" "-v1" "-v2"
)
# Generate permutations
for known in $KNOWN_SUBS; do
base=$(echo $known | sed "s/\.$TARGET//")
# Add prefixes
for prefix in "${PREFIXES[@]}"; do
echo "${prefix}-${base}.${TARGET}"
echo "${prefix}${base}.${TARGET}"
echo "${prefix}.${base}.${TARGET}"
done
# Add suffixes
for suffix in "${SUFFIXES[@]}"; do
echo "${base}${suffix}.${TARGET}"
done
# Environment permutations
echo "${base}.env.${TARGET}"
echo "${base}.environment.${TARGET}"
# Region permutations
for region in "us-east-1" "us-west-2" "eu-west-1" "eu-central-1" "ap-southeast-1" "ap-northeast-1"; do
echo "${base}.${region}.${TARGET}"
done
done > all_permutations.txt
# Resolve with wildcard filtering
puredns resolve all_permutations.txt \
-r resolvers.txt \
--wildcard-batch 1000000 \
--write-massdns massdns_raw.txt \
-o newly_found.txt
echo "[+] New subdomains discovered: $(wc -l < newly_found.txt)"#!/bin/bash
# permutation_engine.sh - Smart DNS permutation attack
TARGET="example.com"
KNOWN_SUBS=$(cat real_subs.txt)
# Common prefixes and suffixes
PREFIXES=(
"dev" "staging" "prod" "test" "beta" "alpha" "demo" "sandbox"
"internal" "external" "private" "public" "secure" "admin"
"management" "dashboard" "portal" "console" "monitor" "metrics"
"logs" "audit" "backup" "replica" "mirror" "cdn" "origin"
"assets" "static" "media" "images" "videos" "files"
"api" "rest" "graphql" "soap" "webhook" "websocket"
"mail" "smtp" "pop3" "imap" "exchange"
"vpn" "proxy" "gateway" "bastion" "jump"
"jenkins" "gitlab" "jira" "confluence" "wiki"
"kibana" "grafana" "prometheus" "nagios" "splunk"
"docker" "k8s" "kubernetes" "cluster" "node"
"us" "eu" "asia" "apac" "emea" "amer"
"us-east" "us-west" "eu-west" "eu-central" "ap-southeast"
"1" "01" "001" "2" "02" "002" "3" "03" "003"
"old" "new" "current" "previous" "legacy"
"v1" "v2" "v3" "version1" "version2"
"app" "web" "mobile" "ios" "android"
"auth" "login" "sso" "oauth" "identity"
"payment" "billing" "checkout" "cart"
"search" "discover" "explore" "trending"
"notifications" "push" "sms" "email"
"docs" "documentation" "help" "support" "faq"
)
SUFFIXES=(
"-dev" "-staging" "-prod" "-test" "-beta" "-old" "-new" "-backup"
"-internal" "-external" "-private" "-public" "-secure" "-admin"
"-api" "-ui" "-svc" "-service" "-app" "-web" "-site"
"-cdn" "-origin" "-proxy" "-gw" "-gateway"
"-us" "-eu" "-asia" "-1" "-2" "-01" "-02" "-v1" "-v2"
)
# Generate permutations
for known in $KNOWN_SUBS; do
base=$(echo $known | sed "s/\.$TARGET//")
# Add prefixes
for prefix in "${PREFIXES[@]}"; do
echo "${prefix}-${base}.${TARGET}"
echo "${prefix}${base}.${TARGET}"
echo "${prefix}.${base}.${TARGET}"
done
# Add suffixes
for suffix in "${SUFFIXES[@]}"; do
echo "${base}${suffix}.${TARGET}"
done
# Environment permutations
echo "${base}.env.${TARGET}"
echo "${base}.environment.${TARGET}"
# Region permutations
for region in "us-east-1" "us-west-2" "eu-west-1" "eu-central-1" "ap-southeast-1" "ap-northeast-1"; do
echo "${base}.${region}.${TARGET}"
done
done > all_permutations.txt
# Resolve with wildcard filtering
puredns resolve all_permutations.txt \
-r resolvers.txt \
--wildcard-batch 1000000 \
--write-massdns massdns_raw.txt \
-o newly_found.txt
echo "[+] New subdomains discovered: $(wc -l < newly_found.txt)"Part 7: ASN to IP Range to Host Mapping
7.1 Complete ASN Enumeration Pipeline
#!/bin/bash
# asn_pipeline.sh - Full ASN to host mapping
TARGET="example.com"
# Step 1: Resolve current IPs
IP=$(dig +short $TARGET | head -1)
# Step 2: Find ASN
ASN=$(whois -h whois.cymru.com " -c $IP" | tail -1 | awk '{print $1}')
echo "[+] ASN: $ASN"
# Step 3: Get all IP ranges for this ASN
echo "[*] Fetching IP ranges for AS$ASN..."
whois -h whois.radb.net -- "-i origin AS$ASN" | \
grep -oP '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/[0-9]+' | \
sort -u > asn_ranges.txt
# Step 4: Get IPv6 ranges too
whois -h whois.radb.net -- "-i origin AS$ASN" | \
grep -oP '[0-9a-fA-F:]+/[0-9]+' | \
sort -u > asn_ranges_ipv6.txt
# Step 5: Scan all ranges for HTTP/HTTPS services
echo "[*] Scanning IP ranges for web services..."
cat asn_ranges.txt | naabu -rate 500 -top-ports 1000 -silent \
-o naabu_ports.txt
# Step 6: Reverse DNS on found IPs
echo "[*] Reverse DNS lookup..."
while read ip; do
dig +short -x $ip >> reverse_dns.txt
done < naabu_ports.txt
# Step 7: HTTP fingerprinting on discovered services
echo "[*] HTTP fingerprinting..."
cat naabu_ports.txt | httpx -silent -title -status-code -tech-detect \
-o fingerprint.txt
# Step 8: Find other domains on same IPs (shared hosting)
echo "[*] Finding co-hosted domains..."
for ip in $(cat naabu_ports.txt | awk -F: '{print $1}' | sort -u); do
curl -s "https://reverse-ip.whoisxmlapi.com/api/v1?ip=$ip" | \
jq -r '.result[]?.name' 2>/dev/null
done | sort -u > cohosted_domains.txt
echo "[+] ASN pipeline complete."#!/bin/bash
# asn_pipeline.sh - Full ASN to host mapping
TARGET="example.com"
# Step 1: Resolve current IPs
IP=$(dig +short $TARGET | head -1)
# Step 2: Find ASN
ASN=$(whois -h whois.cymru.com " -c $IP" | tail -1 | awk '{print $1}')
echo "[+] ASN: $ASN"
# Step 3: Get all IP ranges for this ASN
echo "[*] Fetching IP ranges for AS$ASN..."
whois -h whois.radb.net -- "-i origin AS$ASN" | \
grep -oP '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/[0-9]+' | \
sort -u > asn_ranges.txt
# Step 4: Get IPv6 ranges too
whois -h whois.radb.net -- "-i origin AS$ASN" | \
grep -oP '[0-9a-fA-F:]+/[0-9]+' | \
sort -u > asn_ranges_ipv6.txt
# Step 5: Scan all ranges for HTTP/HTTPS services
echo "[*] Scanning IP ranges for web services..."
cat asn_ranges.txt | naabu -rate 500 -top-ports 1000 -silent \
-o naabu_ports.txt
# Step 6: Reverse DNS on found IPs
echo "[*] Reverse DNS lookup..."
while read ip; do
dig +short -x $ip >> reverse_dns.txt
done < naabu_ports.txt
# Step 7: HTTP fingerprinting on discovered services
echo "[*] HTTP fingerprinting..."
cat naabu_ports.txt | httpx -silent -title -status-code -tech-detect \
-o fingerprint.txt
# Step 8: Find other domains on same IPs (shared hosting)
echo "[*] Finding co-hosted domains..."
for ip in $(cat naabu_ports.txt | awk -F: '{print $1}' | sort -u); do
curl -s "https://reverse-ip.whoisxmlapi.com/api/v1?ip=$ip" | \
jq -r '.result[]?.name' 2>/dev/null
done | sort -u > cohosted_domains.txt
echo "[+] ASN pipeline complete."Part 8: MassDNS & DNS Brute Force (Production-Grade)
8.1 MassDNS Configuration
# Install massDNS
git clone https://github.com/blechschmidt/massdns.git
cd massdns
make
# Prepare resolvers (use verified, high-quality resolvers)
# Download fresh resolver list
wget https://raw.githubusercontent.com/trickest/resolvers/main/resolvers.txt -O resolvers.txt
# Prepare wordlist (combine multiple sources)
cat /usr/share/wordlists/SecLists/Discovery/DNS/subdomains-top1million-110000.txt \
/usr/share/wordlists/SecLists/Discovery/DNS/deepmagic.com-prefixes-top50000.txt \
/usr/share/wordlists/SecLists/Discovery/DNS/combined_subdomains.txt \
| sort -u > mega_wordlist.txt# Install massDNS
git clone https://github.com/blechschmidt/massdns.git
cd massdns
make
# Prepare resolvers (use verified, high-quality resolvers)
# Download fresh resolver list
wget https://raw.githubusercontent.com/trickest/resolvers/main/resolvers.txt -O resolvers.txt
# Prepare wordlist (combine multiple sources)
cat /usr/share/wordlists/SecLists/Discovery/DNS/subdomains-top1million-110000.txt \
/usr/share/wordlists/SecLists/Discovery/DNS/deepmagic.com-prefixes-top50000.txt \
/usr/share/wordlists/SecLists/Discovery/DNS/combined_subdomains.txt \
| sort -u > mega_wordlist.txt8.2 Running MassDNS
# Basic bruteforce
./bin/massdns \
-r resolvers.txt \
-t A \
-w massdns_output.txt \
-o S \
mega_wordlist.txt \
example.com
# With wildcard detection
./bin/massdns \
-r resolvers.txt \
-t A \
-w massdns_wildcard.txt \
-o S \
--wildcard-domain example.com \
mega_wordlist.txt
# Faster with socket count optimization
./bin/massdns \
-r resolvers.txt \
-t A \
-w massdns_fast.txt \
-o S \
-s 10000 \
mega_wordlist.txt
# Process results
grep -E " A " massdns_output.txt | \
awk '{print $1}' | \
sed 's/\.$//' | \
sort -u > dns_found.txt# Basic bruteforce
./bin/massdns \
-r resolvers.txt \
-t A \
-w massdns_output.txt \
-o S \
mega_wordlist.txt \
example.com
# With wildcard detection
./bin/massdns \
-r resolvers.txt \
-t A \
-w massdns_wildcard.txt \
-o S \
--wildcard-domain example.com \
mega_wordlist.txt
# Faster with socket count optimization
./bin/massdns \
-r resolvers.txt \
-t A \
-w massdns_fast.txt \
-o S \
-s 10000 \
mega_wordlist.txt
# Process results
grep -E " A " massdns_output.txt | \
awk '{print $1}' | \
sed 's/\.$//' | \
sort -u > dns_found.txt8.3 PureDNS (Wildcard-Aware Alternative)
# Install puredns
go install github.com/d3mondev/puredns/v2@latest
# Bruteforce with automatic wildcard detection and filtering
puredns bruteforce \
/usr/share/wordlists/SecLists/Discovery/DNS/subdomains-top1million-20000.txt \
example.com \
-r resolvers.txt \
--wildcard-batch 1000000 \
--wildcard-tests 10 \
--rate-limit 10000 \
-o puredns_results.txt
# Resolve existing subdomains (with wildcard filtering)
puredns resolve subdomains.txt \
-r resolvers.txt \
--wildcard-batch 1000000 \
-o resolved_real.txt# Install puredns
go install github.com/d3mondev/puredns/v2@latest
# Bruteforce with automatic wildcard detection and filtering
puredns bruteforce \
/usr/share/wordlists/SecLists/Discovery/DNS/subdomains-top1million-20000.txt \
example.com \
-r resolvers.txt \
--wildcard-batch 1000000 \
--wildcard-tests 10 \
--rate-limit 10000 \
-o puredns_results.txt
# Resolve existing subdomains (with wildcard filtering)
puredns resolve subdomains.txt \
-r resolvers.txt \
--wildcard-batch 1000000 \
-o resolved_real.txtPart 9: Complete OSINT Reconnaissance Pipeline
9.1 The Full Automated Pipeline
#!/bin/bash
# full_recon.sh - Complete OSINT/Recon pipeline for authorized pentesting
DOMAIN="${1:-example.com}"
OUTPUT_DIR="./recon_$(echo $DOMAIN | tr '.' '_')_$(date +%Y%m%d_%H%M%S)"
mkdir -p $OUTPUT_DIR/{passive,active,cloud,historical,github,asn,live}
echo "============================================="
echo " Complete OSINT Reconnaissance Pipeline"
echo " Target: $DOMAIN"
echo " Started: $(date)"
echo "============================================="
# ================================================================
# PHASE 1: PRELIMINARY INFORMATION
# ================================================================
echo "[1/10] Phase 1: Preliminary Information Gathering"
# Basic DNS records
dig +short A $DOMAIN > $OUTPUT_DIR/passive/a_records.txt
dig +short AAAA $DOMAIN > $OUTPUT_DIR/passive/aaaa_records.txt
dig +short MX $DOMAIN | sort -n > $OUTPUT_DIR/passive/mx_records.txt
dig +short NS $DOMAIN > $OUTPUT_DIR/passive/ns_records.txt
dig TXT $DOMAIN +short > $OUTPUT_DIR/passive/txt_records.txt
dig CAA $DOMAIN +short > $OUTPUT_DIR/passive/caa_records.txt
# WHOIS
whois $DOMAIN > $OUTPUT_DIR/passive/whois.txt
# ================================================================
# PHASE 2: CERTIFICATE TRANSPARENCY LOGS
# ================================================================
echo "[2/10] Phase 2: Certificate Transparency Enumeration"
curl -s "https://crt.sh/?q=%25.$DOMAIN&output=json" | \
jq -r '.[].name_value' | \
sed 's/\*\.//g' | \
tr ' ' '\n' | sort -u > $OUTPUT_DIR/passive/crtsh_subs.txt
# Also check identity certificates
curl -s "https://crt.sh/?q=$DOMAIN&output=json" | \
jq -r '.[].name_value' | sort -u >> $OUTPUT_DIR/passive/crtsh_subs.txt
# Search by issuer CA
# curl -s "https://crt.sh/?iCAID=286236&output=json" | \
# jq -r '.[].name_value' | grep -E "\.$DOMAIN$" >> $OUTPUT_DIR/passive/crtsh_subs.txt
sort -u -o $OUTPUT_DIR/passive/crtsh_subs.txt $OUTPUT_DIR/passive/crtsh_subs.txt
echo " -> $(wc -l < $OUTPUT_DIR/passive/crtsh_subs.txt) unique subdomains from CT logs"
# ================================================================
# PHASE 3: PASSIVE SUBDOMAIN AGGREGATION
# ================================================================
echo "[3/10] Phase 3: Multi-Source Passive Aggregation"
# Subfinder
subfinder -d $DOMAIN -all -recursive -silent -o $OUTPUT_DIR/passive/subfinder.txt 2>/dev/null
# Assetfinder
assetfinder --subs-only $DOMAIN > $OUTPUT_DIR/passive/assetfinder.txt 2>/dev/null
# Sublist3r
sublist3r -d $DOMAIN -o $OUTPUT_DIR/passive/sublist3r.txt 2>/dev/null
# Amass (passive only)
amass enum -passive -d $DOMAIN -o $OUTPUT_DIR/passive/amass_passive.txt 2>/dev/null
# Combine all passive sources
cat $OUTPUT_DIR/passive/*.txt | \
grep -E "\.$DOMAIN$" | \
sort -u > $OUTPUT_DIR/passive/all_passive_subs.txt
echo " -> $(wc -l < $OUTPUT_DIR/passive/all_passive_subs.txt) total passive subdomains"
# ================================================================
# PHASE 4: DNS BRUTEFORCE & PERMUTATION
# ================================================================
echo "[4/10] Phase 4: Active DNS Brute Force"
# MassDNS bruteforce
if command -v massdns &> /dev/null; then
massdns \
-r /usr/share/seclists/Discovery/DNS/dns-JH.txt \
-t A \
-o S \
-w $OUTPUT_DIR/active/massdns_output.txt \
/usr/share/wordlists/SecLists/Discovery/DNS/subdomains-top1million-20000.txt \
$DOMAIN 2>/dev/null
grep -E " A " $OUTPUT_DIR/active/massdns_output.txt | \
awk '{print $1}' | sed 's/\.$//' | \
grep -E "\.$DOMAIN$" | sort -u > $OUTPUT_DIR/active/massdns_subs.txt
fi
# puredns if available
if command -v puredns &> /dev/null; then
puredns bruteforce \
/usr/share/wordlists/SecLists/Discovery/DNS/subdomains-top1million-20000.txt \
$DOMAIN \
-r /usr/share/seclists/Discovery/DNS/dns-JH.txt \
--wildcard-batch 1000000 \
-o $OUTPUT_DIR/active/puredns_subs.txt 2>/dev/null
fi
# Permutation attack
cat $OUTPUT_DIR/passive/all_passive_subs.txt $OUTPUT_DIR/active/puredns_subs.txt 2>/dev/null | \
sort -u | dnsgen - > $OUTPUT_DIR/active/permutations.txt 2>/dev/null
if [ -s $OUTPUT_DIR/active/permutations.txt ]; then
puredns resolve $OUTPUT_DIR/active/permutations.txt \
-r /usr/share/seclists/Discovery/DNS/dns-JH.txt \
--wildcard-batch 1000000 \
-o $OUTPUT_DIR/active/permutation_found.txt 2>/dev/null
fi
# ================================================================
# PHASE 5: DNS RESOLUTION & WILDCARD FILTERING
# ================================================================
echo "[5/10] Phase 5: DNS Resolution & Wildcard Filtering"
# Combine all discovered subdomains
cat $OUTPUT_DIR/passive/all_passive_subs.txt \
$OUTPUT_DIR/active/massdns_subs.txt \
$OUTPUT_DIR/active/puredns_subs.txt \
$OUTPUT_DIR/active/permutation_found.txt 2>/dev/null | \
sort -u > $OUTPUT_DIR/live/all_candidates.txt
# Resolve with dnsx (includes wildcard detection)
cat $OUTPUT_DIR/live/all_candidates.txt | \
dnsx -a -resp -silent -wd $DOMAIN -o $OUTPUT_DIR/live/resolved_subs.txt 2>/dev/null
echo " -> $(wc -l < $OUTPUT_DIR/live/resolved_subs.txt) confirmed live subdomains"
# ================================================================
# PHASE 6: HTTP PROBING & FINGERPRINTING
# ================================================================
echo "[6/10] Phase 6: HTTP Liveness & Fingerprinting"
cat $OUTPUT_DIR/live/resolved_subs.txt | \
httpx -silent \
-title \
-status-code \
-tech-detect \
-follow-redirects \
-content-length \
-web-server \
-csp-probe \
-location \
-o $OUTPUT_DIR/live/live_http.txt 2>/dev/null
# Extract CSP domains (often reveals hidden subdomains)
grep -oP "https?://[a-zA-Z0-9.-]+\.$DOMAIN" $OUTPUT_DIR/live/live_http.txt | \
sort -u >> $OUTPUT_DIR/live/csp_revealed_subs.txt
echo " -> $(wc -l < $OUTPUT_DIR/live/live_http.txt) live HTTP services"
# ================================================================
# PHASE 7: HISTORICAL URL DISCOVERY
# ================================================================
echo "[7/10] Phase 7: Historical Data Collection"
# Get all historical URLs
echo "$DOMAIN" | gau --subs --providers wayback,commoncrawl,otx,urlscan \
> $OUTPUT_DIR/historical/all_urls.txt 2>/dev/null
# Extract JavaScript files
grep -E '\.js(\?|$)' $OUTPUT_DIR/historical/all_urls.txt | sort -u \
> $OUTPUT_DIR/historical/js_files.txt
# Extract API endpoints
grep -iE '(api|graphql|v1|v2|v3|endpoint|rest|soap|json|xml)' \
$OUTPUT_DIR/historical/all_urls.txt | sort -u \
> $OUTPUT_DIR/historical/api_endpoints.txt
# Extract parameters for fuzzing
grep -oP '\?[^ ]+' $OUTPUT_DIR/historical/all_urls.txt | \
sed 's/\?//' | tr '&' '\n' | cut -d'=' -f1 | sort -u \
> $OUTPUT_DIR/historical/parameters.txt
# Wayback Machine snapshot timestamps
curl -s "http://web.archive.org/cdx/search/cdx?url=$DOMAIN/*&output=json&fl=timestamp,original,statuscode" \
> $OUTPUT_DIR/historical/wayback_snapshots.json 2>/dev/null
echo " -> $(wc -l < $OUTPUT_DIR/historical/all_urls.txt) historical URLs"
echo " -> $(wc -l < $OUTPUT_DIR/historical/api_endpoints.txt) API endpoints"
echo " -> $(wc -l < $OUTPUT_DIR/historical/parameters.txt) unique parameters"
# ================================================================
# PHASE 8: ASN & IP RANGE ENUMERATION
# ================================================================
echo "[8/10] Phase 8: ASN & Infrastructure Mapping"
# Resolve to IP
IP=$(dig +short $DOMAIN | head -1)
if [ -n "$IP" ]; then
# Get ASN
ASN=$(whois -h whois.cymru.com " -c $IP" 2>/dev/null | tail -1 | awk '{print $1}')
echo "$ASN" > $OUTPUT_DIR/asn/asn.txt
# Get all IP ranges
if [ -n "$ASN" ]; then
whois -h whois.radb.net -- "-i origin AS$ASN" 2>/dev/null | \
grep -oP '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/[0-9]+' | \
sort -u > $OUTPUT_DIR/asn/ip_ranges.txt
fi
# Scan for open ports on resolved subdomains
cat $OUTPUT_DIR/live/resolved_subs.txt | \
naabu -rate 500 -top-ports 1000 -silent -o $OUTPUT_DIR/asn/port_scan.txt 2>/dev/null
fi
echo " -> ASN: $ASN"
echo " -> IP Ranges: $(wc -l < $OUTPUT_DIR/asn/ip_ranges.txt 2>/dev/null || echo 0)"
# ================================================================
# PHASE 9: CLOUD ASSET DISCOVERY
# ================================================================
echo "[9/10] Phase 9: Cloud Asset Discovery"
# S3 bucket enumeration
if command -v s3scanner &> /dev/null; then
s3scanner --bucket-file $OUTPUT_DIR/passive/all_passive_subs.txt \
--out-file $OUTPUT_DIR/cloud/s3_buckets.txt 2>/dev/null
fi
# Cloud_enum
if command -v cloud_enum &> /dev/null; then
cloud_enum -k "$(echo $DOMAIN | cut -d. -f1)" \
-k "$DOMAIN" \
-k "example" \
-l $OUTPUT_DIR/cloud/cloud_assets.txt 2>/dev/null
fi
# ================================================================
# PHASE 10: TECHNOLOGY STACK & VULNERABILITY ANALYSIS
# ================================================================
echo "[10/10] Phase 10: Technology Stack Analysis"
# WAF detection
wafw00f $DOMAIN -o $OUTPUT_DIR/live/waf.txt 2>/dev/null
# Technology stack
curl -s -I "https://$DOMAIN" > $OUTPUT_DIR/live/http_headers.txt
# Screenshots of live subdomains (if gowitness installed)
if command -v gowitness &> /dev/null; then
cat $OUTPUT_DIR/live/live_http.txt | awk '{print $2}' | \
gowitness file -f - -P $OUTPUT_DIR/live/screenshots/ 2>/dev/null
fi
# ================================================================
# FINAL SUMMARY
# ================================================================
echo ""
echo "============================================="
echo " RECONNAISSANCE COMPLETE"
echo "============================================="
echo " Target: $DOMAIN"
echo " Output: $OUTPUT_DIR"
echo " Date: $(date)"
echo "---------------------------------------------"
echo " Summary:"
echo " - Subdomains (CT logs): $(wc -l < $OUTPUT_DIR/passive/crtsh_subs.txt 2>/dev/null || echo 0)"
echo " - Subdomains (passive total): $(wc -l < $OUTPUT_DIR/passive/all_passive_subs.txt 2>/dev/null || echo 0)"
echo " - Resolved (live DNS): $(wc -l < $OUTPUT_DIR/live/resolved_subs.txt 2>/dev/null || echo 0)"
echo " - HTTP services (live): $(wc -l < $OUTPUT_DIR/live/live_http.txt 2>/dev/null || echo 0)"
echo " - Historical URLs: $(wc -l < $OUTPUT_DIR/historical/all_urls.txt 2>/dev/null || echo 0)"
echo " - API endpoints: $(wc -l < $OUTPUT_DIR/historical/api_endpoints.txt 2>/dev/null || echo 0)"
echo " - JS files: $(wc -l < $OUTPUT_DIR/historical/js_files.txt 2>/dev/null || echo 0)"
echo " - Unique parameters: $(wc -l < $OUTPUT_DIR/historical/parameters.txt 2>/dev/null || echo 0)"
echo " - ASN: $(cat $OUTPUT_DIR/asn/asn.txt 2>/dev/null || echo 'N/A')"
echo "============================================="#!/bin/bash
# full_recon.sh - Complete OSINT/Recon pipeline for authorized pentesting
DOMAIN="${1:-example.com}"
OUTPUT_DIR="./recon_$(echo $DOMAIN | tr '.' '_')_$(date +%Y%m%d_%H%M%S)"
mkdir -p $OUTPUT_DIR/{passive,active,cloud,historical,github,asn,live}
echo "============================================="
echo " Complete OSINT Reconnaissance Pipeline"
echo " Target: $DOMAIN"
echo " Started: $(date)"
echo "============================================="
# ================================================================
# PHASE 1: PRELIMINARY INFORMATION
# ================================================================
echo "[1/10] Phase 1: Preliminary Information Gathering"
# Basic DNS records
dig +short A $DOMAIN > $OUTPUT_DIR/passive/a_records.txt
dig +short AAAA $DOMAIN > $OUTPUT_DIR/passive/aaaa_records.txt
dig +short MX $DOMAIN | sort -n > $OUTPUT_DIR/passive/mx_records.txt
dig +short NS $DOMAIN > $OUTPUT_DIR/passive/ns_records.txt
dig TXT $DOMAIN +short > $OUTPUT_DIR/passive/txt_records.txt
dig CAA $DOMAIN +short > $OUTPUT_DIR/passive/caa_records.txt
# WHOIS
whois $DOMAIN > $OUTPUT_DIR/passive/whois.txt
# ================================================================
# PHASE 2: CERTIFICATE TRANSPARENCY LOGS
# ================================================================
echo "[2/10] Phase 2: Certificate Transparency Enumeration"
curl -s "https://crt.sh/?q=%25.$DOMAIN&output=json" | \
jq -r '.[].name_value' | \
sed 's/\*\.//g' | \
tr ' ' '\n' | sort -u > $OUTPUT_DIR/passive/crtsh_subs.txt
# Also check identity certificates
curl -s "https://crt.sh/?q=$DOMAIN&output=json" | \
jq -r '.[].name_value' | sort -u >> $OUTPUT_DIR/passive/crtsh_subs.txt
# Search by issuer CA
# curl -s "https://crt.sh/?iCAID=286236&output=json" | \
# jq -r '.[].name_value' | grep -E "\.$DOMAIN$" >> $OUTPUT_DIR/passive/crtsh_subs.txt
sort -u -o $OUTPUT_DIR/passive/crtsh_subs.txt $OUTPUT_DIR/passive/crtsh_subs.txt
echo " -> $(wc -l < $OUTPUT_DIR/passive/crtsh_subs.txt) unique subdomains from CT logs"
# ================================================================
# PHASE 3: PASSIVE SUBDOMAIN AGGREGATION
# ================================================================
echo "[3/10] Phase 3: Multi-Source Passive Aggregation"
# Subfinder
subfinder -d $DOMAIN -all -recursive -silent -o $OUTPUT_DIR/passive/subfinder.txt 2>/dev/null
# Assetfinder
assetfinder --subs-only $DOMAIN > $OUTPUT_DIR/passive/assetfinder.txt 2>/dev/null
# Sublist3r
sublist3r -d $DOMAIN -o $OUTPUT_DIR/passive/sublist3r.txt 2>/dev/null
# Amass (passive only)
amass enum -passive -d $DOMAIN -o $OUTPUT_DIR/passive/amass_passive.txt 2>/dev/null
# Combine all passive sources
cat $OUTPUT_DIR/passive/*.txt | \
grep -E "\.$DOMAIN$" | \
sort -u > $OUTPUT_DIR/passive/all_passive_subs.txt
echo " -> $(wc -l < $OUTPUT_DIR/passive/all_passive_subs.txt) total passive subdomains"
# ================================================================
# PHASE 4: DNS BRUTEFORCE & PERMUTATION
# ================================================================
echo "[4/10] Phase 4: Active DNS Brute Force"
# MassDNS bruteforce
if command -v massdns &> /dev/null; then
massdns \
-r /usr/share/seclists/Discovery/DNS/dns-JH.txt \
-t A \
-o S \
-w $OUTPUT_DIR/active/massdns_output.txt \
/usr/share/wordlists/SecLists/Discovery/DNS/subdomains-top1million-20000.txt \
$DOMAIN 2>/dev/null
grep -E " A " $OUTPUT_DIR/active/massdns_output.txt | \
awk '{print $1}' | sed 's/\.$//' | \
grep -E "\.$DOMAIN$" | sort -u > $OUTPUT_DIR/active/massdns_subs.txt
fi
# puredns if available
if command -v puredns &> /dev/null; then
puredns bruteforce \
/usr/share/wordlists/SecLists/Discovery/DNS/subdomains-top1million-20000.txt \
$DOMAIN \
-r /usr/share/seclists/Discovery/DNS/dns-JH.txt \
--wildcard-batch 1000000 \
-o $OUTPUT_DIR/active/puredns_subs.txt 2>/dev/null
fi
# Permutation attack
cat $OUTPUT_DIR/passive/all_passive_subs.txt $OUTPUT_DIR/active/puredns_subs.txt 2>/dev/null | \
sort -u | dnsgen - > $OUTPUT_DIR/active/permutations.txt 2>/dev/null
if [ -s $OUTPUT_DIR/active/permutations.txt ]; then
puredns resolve $OUTPUT_DIR/active/permutations.txt \
-r /usr/share/seclists/Discovery/DNS/dns-JH.txt \
--wildcard-batch 1000000 \
-o $OUTPUT_DIR/active/permutation_found.txt 2>/dev/null
fi
# ================================================================
# PHASE 5: DNS RESOLUTION & WILDCARD FILTERING
# ================================================================
echo "[5/10] Phase 5: DNS Resolution & Wildcard Filtering"
# Combine all discovered subdomains
cat $OUTPUT_DIR/passive/all_passive_subs.txt \
$OUTPUT_DIR/active/massdns_subs.txt \
$OUTPUT_DIR/active/puredns_subs.txt \
$OUTPUT_DIR/active/permutation_found.txt 2>/dev/null | \
sort -u > $OUTPUT_DIR/live/all_candidates.txt
# Resolve with dnsx (includes wildcard detection)
cat $OUTPUT_DIR/live/all_candidates.txt | \
dnsx -a -resp -silent -wd $DOMAIN -o $OUTPUT_DIR/live/resolved_subs.txt 2>/dev/null
echo " -> $(wc -l < $OUTPUT_DIR/live/resolved_subs.txt) confirmed live subdomains"
# ================================================================
# PHASE 6: HTTP PROBING & FINGERPRINTING
# ================================================================
echo "[6/10] Phase 6: HTTP Liveness & Fingerprinting"
cat $OUTPUT_DIR/live/resolved_subs.txt | \
httpx -silent \
-title \
-status-code \
-tech-detect \
-follow-redirects \
-content-length \
-web-server \
-csp-probe \
-location \
-o $OUTPUT_DIR/live/live_http.txt 2>/dev/null
# Extract CSP domains (often reveals hidden subdomains)
grep -oP "https?://[a-zA-Z0-9.-]+\.$DOMAIN" $OUTPUT_DIR/live/live_http.txt | \
sort -u >> $OUTPUT_DIR/live/csp_revealed_subs.txt
echo " -> $(wc -l < $OUTPUT_DIR/live/live_http.txt) live HTTP services"
# ================================================================
# PHASE 7: HISTORICAL URL DISCOVERY
# ================================================================
echo "[7/10] Phase 7: Historical Data Collection"
# Get all historical URLs
echo "$DOMAIN" | gau --subs --providers wayback,commoncrawl,otx,urlscan \
> $OUTPUT_DIR/historical/all_urls.txt 2>/dev/null
# Extract JavaScript files
grep -E '\.js(\?|$)' $OUTPUT_DIR/historical/all_urls.txt | sort -u \
> $OUTPUT_DIR/historical/js_files.txt
# Extract API endpoints
grep -iE '(api|graphql|v1|v2|v3|endpoint|rest|soap|json|xml)' \
$OUTPUT_DIR/historical/all_urls.txt | sort -u \
> $OUTPUT_DIR/historical/api_endpoints.txt
# Extract parameters for fuzzing
grep -oP '\?[^ ]+' $OUTPUT_DIR/historical/all_urls.txt | \
sed 's/\?//' | tr '&' '\n' | cut -d'=' -f1 | sort -u \
> $OUTPUT_DIR/historical/parameters.txt
# Wayback Machine snapshot timestamps
curl -s "http://web.archive.org/cdx/search/cdx?url=$DOMAIN/*&output=json&fl=timestamp,original,statuscode" \
> $OUTPUT_DIR/historical/wayback_snapshots.json 2>/dev/null
echo " -> $(wc -l < $OUTPUT_DIR/historical/all_urls.txt) historical URLs"
echo " -> $(wc -l < $OUTPUT_DIR/historical/api_endpoints.txt) API endpoints"
echo " -> $(wc -l < $OUTPUT_DIR/historical/parameters.txt) unique parameters"
# ================================================================
# PHASE 8: ASN & IP RANGE ENUMERATION
# ================================================================
echo "[8/10] Phase 8: ASN & Infrastructure Mapping"
# Resolve to IP
IP=$(dig +short $DOMAIN | head -1)
if [ -n "$IP" ]; then
# Get ASN
ASN=$(whois -h whois.cymru.com " -c $IP" 2>/dev/null | tail -1 | awk '{print $1}')
echo "$ASN" > $OUTPUT_DIR/asn/asn.txt
# Get all IP ranges
if [ -n "$ASN" ]; then
whois -h whois.radb.net -- "-i origin AS$ASN" 2>/dev/null | \
grep -oP '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/[0-9]+' | \
sort -u > $OUTPUT_DIR/asn/ip_ranges.txt
fi
# Scan for open ports on resolved subdomains
cat $OUTPUT_DIR/live/resolved_subs.txt | \
naabu -rate 500 -top-ports 1000 -silent -o $OUTPUT_DIR/asn/port_scan.txt 2>/dev/null
fi
echo " -> ASN: $ASN"
echo " -> IP Ranges: $(wc -l < $OUTPUT_DIR/asn/ip_ranges.txt 2>/dev/null || echo 0)"
# ================================================================
# PHASE 9: CLOUD ASSET DISCOVERY
# ================================================================
echo "[9/10] Phase 9: Cloud Asset Discovery"
# S3 bucket enumeration
if command -v s3scanner &> /dev/null; then
s3scanner --bucket-file $OUTPUT_DIR/passive/all_passive_subs.txt \
--out-file $OUTPUT_DIR/cloud/s3_buckets.txt 2>/dev/null
fi
# Cloud_enum
if command -v cloud_enum &> /dev/null; then
cloud_enum -k "$(echo $DOMAIN | cut -d. -f1)" \
-k "$DOMAIN" \
-k "example" \
-l $OUTPUT_DIR/cloud/cloud_assets.txt 2>/dev/null
fi
# ================================================================
# PHASE 10: TECHNOLOGY STACK & VULNERABILITY ANALYSIS
# ================================================================
echo "[10/10] Phase 10: Technology Stack Analysis"
# WAF detection
wafw00f $DOMAIN -o $OUTPUT_DIR/live/waf.txt 2>/dev/null
# Technology stack
curl -s -I "https://$DOMAIN" > $OUTPUT_DIR/live/http_headers.txt
# Screenshots of live subdomains (if gowitness installed)
if command -v gowitness &> /dev/null; then
cat $OUTPUT_DIR/live/live_http.txt | awk '{print $2}' | \
gowitness file -f - -P $OUTPUT_DIR/live/screenshots/ 2>/dev/null
fi
# ================================================================
# FINAL SUMMARY
# ================================================================
echo ""
echo "============================================="
echo " RECONNAISSANCE COMPLETE"
echo "============================================="
echo " Target: $DOMAIN"
echo " Output: $OUTPUT_DIR"
echo " Date: $(date)"
echo "---------------------------------------------"
echo " Summary:"
echo " - Subdomains (CT logs): $(wc -l < $OUTPUT_DIR/passive/crtsh_subs.txt 2>/dev/null || echo 0)"
echo " - Subdomains (passive total): $(wc -l < $OUTPUT_DIR/passive/all_passive_subs.txt 2>/dev/null || echo 0)"
echo " - Resolved (live DNS): $(wc -l < $OUTPUT_DIR/live/resolved_subs.txt 2>/dev/null || echo 0)"
echo " - HTTP services (live): $(wc -l < $OUTPUT_DIR/live/live_http.txt 2>/dev/null || echo 0)"
echo " - Historical URLs: $(wc -l < $OUTPUT_DIR/historical/all_urls.txt 2>/dev/null || echo 0)"
echo " - API endpoints: $(wc -l < $OUTPUT_DIR/historical/api_endpoints.txt 2>/dev/null || echo 0)"
echo " - JS files: $(wc -l < $OUTPUT_DIR/historical/js_files.txt 2>/dev/null || echo 0)"
echo " - Unique parameters: $(wc -l < $OUTPUT_DIR/historical/parameters.txt 2>/dev/null || echo 0)"
echo " - ASN: $(cat $OUTPUT_DIR/asn/asn.txt 2>/dev/null || echo 'N/A')"
echo "============================================="Part 10: Vulnerability-Specific Enumeration
10.1 Subdomain Takeover Testing
#!/bin/bash
# takeover_test.sh - Subdomain takeover detection
TARGET="example.com"
# Method 1: subjack
subjack -w resolved_subs.txt \
-t 100 \
-timeout 30 \
-ssl \
-v \
-o takeover_subjack.txt
# Method 2: subover
subover -l resolved_subs.txt -t 50
# Method 3: nuclei
nuclei -l resolved_subs.txt -t ~/nuclei-templates/takeovers/ -o takeover_nuclei.txt
# Method 4: Manual CNAME inspection
while read sub; do
cname=$(dig +short CNAME "$sub" | head -1)
if [ -n "$cname" ]; then
echo "$sub → CNAME: $cname"
# Check if CNAME points to deprovisioned cloud resources
echo "$cname" | grep -qiE "(s3\.amazonaws\.com|cloudfront\.net|azureedge\.net|azurewebsites\.net|herokuapp\.com|github\.io|firebaseio\.com|dream\.io|unbounce\.com|surge\.sh|bitbucket\.io|pantheon\.io|zendesk\.com|helpscout\.net|fastly\.net|trafficmanager\.net|elasticbeanstalk\.com)"
if [ $? -eq 0 ]; then
echo "[!!!] POTENTIAL TAKEOVER: $sub → $cname"
fi
fi
done < resolved_subs.txt#!/bin/bash
# takeover_test.sh - Subdomain takeover detection
TARGET="example.com"
# Method 1: subjack
subjack -w resolved_subs.txt \
-t 100 \
-timeout 30 \
-ssl \
-v \
-o takeover_subjack.txt
# Method 2: subover
subover -l resolved_subs.txt -t 50
# Method 3: nuclei
nuclei -l resolved_subs.txt -t ~/nuclei-templates/takeovers/ -o takeover_nuclei.txt
# Method 4: Manual CNAME inspection
while read sub; do
cname=$(dig +short CNAME "$sub" | head -1)
if [ -n "$cname" ]; then
echo "$sub → CNAME: $cname"
# Check if CNAME points to deprovisioned cloud resources
echo "$cname" | grep -qiE "(s3\.amazonaws\.com|cloudfront\.net|azureedge\.net|azurewebsites\.net|herokuapp\.com|github\.io|firebaseio\.com|dream\.io|unbounce\.com|surge\.sh|bitbucket\.io|pantheon\.io|zendesk\.com|helpscout\.net|fastly\.net|trafficmanager\.net|elasticbeanstalk\.com)"
if [ $? -eq 0 ]; then
echo "[!!!] POTENTIAL TAKEOVER: $sub → $cname"
fi
fi
done < resolved_subs.txt10.2 CORS Misconfiguration Discovery
# Test each subdomain for CORS misconfigurations
while read sub; do
echo "[*] Testing CORS on $sub"
curl -s -I -H "Origin: https://evil.com" -H "Host: $sub" "https://$sub" | \
grep -i "access-control-allow-origin"
done < resolved_subs.txt | grep -v "^$"# Test each subdomain for CORS misconfigurations
while read sub; do
echo "[*] Testing CORS on $sub"
curl -s -I -H "Origin: https://evil.com" -H "Host: $sub" "https://$sub" | \
grep -i "access-control-allow-origin"
done < resolved_subs.txt | grep -v "^$"10.3 Open Ports & Service Discovery
# Full port scan on all live subdomains
naabu -list resolved_subs.txt \
-rate 1000 \
-top-ports 1000 \
-silent \
-o open_ports.txt
# Service version detection
nmap -sV -sC -iL resolved_subs.txt \
-p 80,443,8080,8443,3000,5000,9000 \
-oA nmap_scan# Full port scan on all live subdomains
naabu -list resolved_subs.txt \
-rate 1000 \
-top-ports 1000 \
-silent \
-o open_ports.txt
# Service version detection
nmap -sV -sC -iL resolved_subs.txt \
-p 80,443,8080,8443,3000,5000,9000 \
-oA nmap_scanPart 11: Real-World Attack Surface Summary for example.com
Based on all the enumeration performed, here is the complete attack surface:
11.1 Confirmed Subdomains
example.com (root)
├── www.example.com (redirect)
├── api.example.com (REST API)
├── static.example.com (static assets)
├── cdn-client.example.com (client CDN)
├── cdn-static-1.example.com (static CDN)
├── cdn-images-1.example.com (image CDN v1)
├── cdn-images-2.example.com (image CDN v2)
├── cdn-audio-1.example.com (audio CDN)
├── miro.example.com (image processing)
├── glyph.example.com (icons/fonts)
├── help.example.com (help center)
├── blog.example.com (engineering blog)
├── about.example.com (about page)
├── policy.example.com (legal/policy)
├── jobs.example.com (careers)
├── publishers.example.com (publisher portal)
├── brands.example.com (brand assets)
├── collateral.example.com (marketing)
├── noteworthy.example.com (publication)
├── yourfriends.example.com (social)
├── snowflake.example.com (internal tool)
└── url2204.mail.example.com (email tracking)example.com (root)
├── www.example.com (redirect)
├── api.example.com (REST API)
├── static.example.com (static assets)
├── cdn-client.example.com (client CDN)
├── cdn-static-1.example.com (static CDN)
├── cdn-images-1.example.com (image CDN v1)
├── cdn-images-2.example.com (image CDN v2)
├── cdn-audio-1.example.com (audio CDN)
├── miro.example.com (image processing)
├── glyph.example.com (icons/fonts)
├── help.example.com (help center)
├── blog.example.com (engineering blog)
├── about.example.com (about page)
├── policy.example.com (legal/policy)
├── jobs.example.com (careers)
├── publishers.example.com (publisher portal)
├── brands.example.com (brand assets)
├── collateral.example.com (marketing)
├── noteworthy.example.com (publication)
├── yourfriends.example.com (social)
├── snowflake.example.com (internal tool)
└── url2204.mail.example.com (email tracking)11.2 Infrastructure Stack
11.3 Security Posture Assessment
Part 12: Conclusion & Best Practices
The Complete Reconnaissance Workflow
Phase 1: PRELIMINARY
├── DNS Records (A, AAAA, MX, NS, TXT, CAA, SOA)
├── WHOIS Lookup
└── SSL/TLS Certificate Analysis
Phase 2: PASSIVE ENUMERATION
├── Certificate Transparency (crt.sh)
├── Search Engines (Google, Bing Dorking)
├── DNS Aggregators (SecurityTrails, VirusTotal)
├── Subdomain Discovery Tools (subfinder, assetfinder)
└── Public Datasets (Chaos, ProjectDiscovery)
Phase 3: ACTIVE ENUMERATION
├── DNS Brute Force (massdns, puredns)
├── Permutation Attack (dnsgen)
├── Virtual Host Discovery (ffuf, gobuster)
└── Port Scanning (naabu, nmap)
Phase 4: CONTENT DISCOVERY
├── Directory Brute Force (ffuf, dirsearch)
├── Historical URL Analysis (gau, wayback)
├── JavaScript Analysis (LinkFinder, SecretFinder)
├── Cloud Asset Discovery (cloud_enum, s3scanner)
└── Technology Fingerprinting (httpx, whatweb)
Phase 5: VULNERABILITY ASSESSMENT
├── Subdomain Takeover (subjack, nuclei)
├── CORS Misconfiguration
├── Open Port Service Detection
├── WAF Detection & Bypass
└── Screenshots & Manual ReviewPhase 1: PRELIMINARY
├── DNS Records (A, AAAA, MX, NS, TXT, CAA, SOA)
├── WHOIS Lookup
└── SSL/TLS Certificate Analysis
Phase 2: PASSIVE ENUMERATION
├── Certificate Transparency (crt.sh)
├── Search Engines (Google, Bing Dorking)
├── DNS Aggregators (SecurityTrails, VirusTotal)
├── Subdomain Discovery Tools (subfinder, assetfinder)
└── Public Datasets (Chaos, ProjectDiscovery)
Phase 3: ACTIVE ENUMERATION
├── DNS Brute Force (massdns, puredns)
├── Permutation Attack (dnsgen)
├── Virtual Host Discovery (ffuf, gobuster)
└── Port Scanning (naabu, nmap)
Phase 4: CONTENT DISCOVERY
├── Directory Brute Force (ffuf, dirsearch)
├── Historical URL Analysis (gau, wayback)
├── JavaScript Analysis (LinkFinder, SecretFinder)
├── Cloud Asset Discovery (cloud_enum, s3scanner)
└── Technology Fingerprinting (httpx, whatweb)
Phase 5: VULNERABILITY ASSESSMENT
├── Subdomain Takeover (subjack, nuclei)
├── CORS Misconfiguration
├── Open Port Service Detection
├── WAF Detection & Bypass
└── Screenshots & Manual ReviewKey Takeaways
- CT logs are the #1 passive source — always start with crt.sh before any other enumeration
- Wildcard DNS kills naive brute-force — always use wildcard-aware tools (puredns, dnsx -wd)
- Combine 10+ passive sources — no single source has complete data
- Permutation attack finds the hidden gold — staging, dev, old versions of known subdomains
- Historical data reveals forgotten assets — Wayback Machine often finds endpoints that still work
- JavaScript files leak everything — API keys, internal URLs, hidden routes
- ASN enumeration expands the scope — find all assets sharing the same infrastructure
- GitHub is the biggest leak — always search for hardcoded credentials and internal references
This complete pipeline transforms a single domain like exampl.com into a comprehensive attack surface map spanning subdomains, IP ranges, cloud assets, employee information, historical endpoints, and potential vulnerabilities — all within the bounds of an authorized penetration test.
GitHub: SecurityTalent | Medium: Security Talent | Twitter: Securi3yTalent | Facebook: Securi3ytalent | Telegram: Securi3yTalent
#BugBounty #CyberSecurity #EthicalHacking #WebSecurity #OSINT #Reconnaissance #AppSec #InfoSec #BugHunter #PenetrationTesting #AttackSurface #SubdomainEnumeration #DNSRecon #SecurityResearch #VulnerabilityResearch #OWASP #WebHacking #CloudSecurity #DevSecOps #RedTeam