Subdomain Takeover: How It Happens and How to Prevent It
Subdomain takeover lets attackers claim your dangling DNS records and serve content from your domain. Learn how to find dangling subdomains, which services are vulnerable, and how to monitor your DNS.
Subdomain takeover is a vulnerability where an attacker can claim control of a subdomain by exploiting a dangling DNS record. When staging.yourdomain.com points to a cloud service you've decommissioned, anyone can register that service and host content on your subdomain — with a valid SSL certificate, your domain's reputation, and full access to cookies scoped to *.yourdomain.com.
It's consistently rated among the top findings in bug bounty programs and requires no exploitation of your code — just knowledge of your DNS.
How Subdomain Takeover Works
- You create
staging.yourdomain.compointing toyour-app.herokuapp.com - You shut down the Heroku app but forget to delete the DNS record
- The CNAME points to
your-app.herokuapp.com— which no longer exists - An attacker registers
your-app.herokuapp.comon their Heroku account - They now receive all traffic to
staging.yourdomain.com - They serve malicious content, capture cookies, or run phishing campaigns — all from your domain
The attacker's site gets a valid TLS certificate via Let's Encrypt or the platform's cert issuance, so there's no browser warning.
Why This Is Serious
From your domain's subdomain, an attacker can:
- Set cookies scoped to
.yourdomain.com(affecting your main site if cookies usedomain=.yourdomain.com) - Phish users — email campaigns linking to
support.yourdomain.comlook legitimate - Bypass CORS — if your API whitelists
*.yourdomain.com - Bypass CSP —
*.yourdomain.cominscript-srcallows their scripts - Undermine your brand and trust
High-severity findings in bug bounty programs regularly receive $1,000–$5,000+ for subdomain takeovers on production domains.
Services Commonly Vulnerable to Takeover
Any cloud service where you can claim a specific subdomain/instance name and that instance doesn't exist:
| Service | DNS Pattern | Risk |
|---|---|---|
| GitHub Pages | yourdomain.github.io | High |
| Heroku | your-app.herokuapp.com | High |
| Netlify | your-site.netlify.app | Medium |
| Vercel | your-project.vercel.app | Medium |
| AWS S3 | bucket.s3.amazonaws.com | High |
| AWS Elastic Beanstalk | app.elasticbeanstalk.com | High |
| Azure | various .azurewebsites.net, .cloudapp.net | High |
| Shopify | custom.myshopify.com | Medium |
| Zendesk | yourdomain.zendesk.com | Medium |
| Fastly | CNAME to Fastly CDN | High |
A dangling CNAME pointing to an unclaimed instance on any of these services is a takeover risk.
Finding Dangling Subdomains
Step 1: Enumerate all your subdomains
# Using subfinder (passive DNS enumeration)
subfinder -d yourdomain.com -all -o subdomains.txt
# Using amass
amass enum -d yourdomain.com -o subdomains.txt
# From Certificate Transparency logs
curl "https://crt.sh/?q=%.yourdomain.com&output=json" | \
jq -r '.[].name_value' | sort -u > ct-subdomains.txt
Step 2: Check each subdomain's CNAME
# Check CNAME records
while read subdomain; do
cname=$(dig CNAME "$subdomain" +short)
if [ -n "$cname" ]; then
echo "$subdomain -> $cname"
fi
done < subdomains.txt
Step 3: Check if CNAME targets exist
# For each CNAME, check if the target resolves
while read subdomain; do
cname=$(dig CNAME "$subdomain" +short | tr -d '.')
if [ -n "$cname" ]; then
target_ip=$(dig A "$cname" +short)
if [ -z "$target_ip" ]; then
echo "POTENTIAL DANGLING CNAME: $subdomain -> $cname (no A record)"
fi
fi
done < subdomains.txt
Using automated tools
# subjack: checks for dangling CNAMEs against known vulnerable services
go install github.com/haccer/subjack@latest
subjack -w subdomains.txt -t 100 -timeout 30 -o results.txt -ssl
# nuclei templates for subdomain takeover
nuclei -l subdomains.txt -t takeovers/
Prevention and Remediation
1. Delete DNS records before decommissioning services
Make DNS record cleanup part of your decommissioning checklist:
Decommission checklist:
□ Remove service/resource
□ Delete or update DNS CNAME records pointing to the service
□ Wait for DNS TTL expiry before considering cleanup complete
□ Verify: dig CNAME staging.yourdomain.com returns NXDOMAIN
This sounds simple but is the most commonly missed step. Teams focus on deleting the resource and forget the DNS record.
2. Audit your DNS quarterly
Pull all DNS records and check each CNAME and A record resolves correctly:
# Export all DNS records (e.g., from Route 53)
aws route53 list-resource-record-sets \
--hosted-zone-id YOUR_ZONE_ID \
--output json | jq -r '.ResourceRecordSets[] | "\(.Type) \(.Name) \(.ResourceRecords[0].Value // .AliasTarget.DNSName // "N/A")"'
Check each CNAME points to an active resource you own.
3. Avoid wildcard DNS records
# ❌ Risky: any subdomain resolves to your IP
*.yourdomain.com A 1.2.3.4
Wildcard records don't directly cause takeovers, but they mask dangling CNAMEs in enumeration and can create other attack surfaces.
4. Use subresource integrity for third-party scripts
If you allow subdomains in your CSP's script-src, use SRI hashes to ensure scripts haven't been replaced:
<script
src="https://static.yourdomain.com/analytics.js"
integrity="sha256-abc123..."
crossorigin="anonymous">
</script>
5. Restrict cookie scope
If possible, don't set cookies with domain=.yourdomain.com (note the leading dot, which covers all subdomains). Cookie theft through a subdomain takeover is only effective if cookies are scoped to the parent domain.
Continuous Monitoring
Set up ongoing monitoring rather than relying on periodic audits:
# GitHub Actions: check for dangling CNAMEs weekly
name: DNS Audit
on:
schedule:
- cron: '0 9 * * 1' # Every Monday 9am
jobs:
dns-audit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install tools
run: go install github.com/haccer/subjack@latest
- name: Enumerate subdomains
run: subfinder -d ${{ secrets.DOMAIN }} -o subdomains.txt
- name: Check for takeovers
run: subjack -w subdomains.txt -t 100 -o findings.txt -ssl
- name: Alert if findings
if: ${{ hashFiles('findings.txt') != '' }}
run: cat findings.txt && exit 1
Bug bounty programs are also an effective passive monitoring mechanism — researchers regularly scan for subdomain takeovers, and responsible disclosure provides an early warning system.