Subdomain Takeover - Übernahme verwaister Subdomains
A subdomain takeover occurs when a DNS record for a subdomain still points to an external service that is no longer active. Attackers can take over the service account and host their own content under the legitimate subdomain. Typical vectors: GitHub Pages, Heroku, Azure, Netlify, AWS S3 buckets with DNS records not removed after account termination. Impact: Phishing under a legitimate domain, cookie theft, content spoofing, XSS against the main domain. Protection: Regular DNS audits, immediate CNAME cleanup.
Subdomain Takeover is a common vulnerability in modern cloud infrastructure: Teams set up subdomains for temporary services, delete the service—but forget to remove the DNS record. For months, staging.company.com continues to point via CNAME to a Heroku app that has already been deleted. Anyone who recreates this app on Heroku (same app name) automatically takes over the subdomain.
Basic Technical Principle
Normal Flow (Secure):
staging.company.com → CNAME → myapp.herokuapp.com → active app
Forgotten DNS Entry (Vulnerable):
staging.company.com → CNAME → myapp.herokuapp.com → App DELETED!
What happens:
- Browser asks: staging.company.com?
- DNS responds: CNAME myapp.herokuapp.com
- Heroku: "myapp" no longer registered → Error 404
Attack:
- Attacker finds orphaned DNS record
- Logs into Heroku and creates app "myapp"
- App is now active again!
- staging.company.com → points to attacker's app!
Consequences:
- Phishing sites under the legitimate domain company.com
- Same domain = browser accepts cookies from company.com! (
document.cookie→ session cookies readable if HttpOnly is missing!) - SPF/DMARC bypass: Emails from staging.company.com appear legitimate
- XSS attacks against users of company.com (Same-Origin Policy!)
- Content spoofing for social engineering
Affected Services and Identification Characteristics
GitHub Pages
- CNAME points to: username.github.io
- Error message: "There isn't a GitHub Pages site here"
- Takeover: Create a GitHub account + repository with the same name + enable Pages
Heroku
- CNAME points to: appname.herokuapp.com
- Error message: "No such app" or custom Heroku error page
- Takeover: Create a Heroku account + app with the same name
AWS S3 Bucket
- CNAME points to: bucket.s3.amazonaws.com
- Error message: "NoSuchBucket" in XML response
- Takeover: Create an AWS account + create a bucket with the same name in the same region
Azure
- App Service:
*.azurewebsites.net- deleted but DNS still active - CDN:
*.azureedge.net - Traffic Manager:
*.trafficmanager.net - Azure Static Web App:
*.azurestaticapps.net
Netlify
- CNAME points to:
*.netlify.appor*.netlify.com - Takeover: Claim Netlify account + site with custom domain
Fastly
- CNAME pointing to
*.fastly.net→ Fastly customer service configuration deleted - Takeover: Claim Fastly account + same backend
WordPress.com
- CNAME pointing to
*.wordpress.com→ Blog deleted - Takeover: New WordPress.com blog with same custom domain claim
> All vulnerable services (200+ documented): https://github.com/EdOverflow/can-i-take-over-xyz - shows whether a service is vulnerable and how the takeover occurs.
Detection in the Penetration Test
1. Subdomain Discovery
# Find all subdomains (via CT logs + DNS brute force):
subfinder -d company.com -all -v -o subdomains.txt
amass enum -d company.com -o subdomains-amass.txt
# From Certificate Transparency (crt.sh):
curl -s "https://crt.sh/?q=%25.company.com&output;=json" | \
python3 -c "import json,sys; [print(c['name_value']) for c in json.load(sys.stdin)]" \
| sort -u > subdomains-ct.txt
2. DNS Resolution and CNAME Check
# Check all subdomains for CNAME:
cat subdomains.txt | while read sub; do
cname=$(dig +short CNAME $sub)
if [ -n "$cname" ]; then
echo "$sub → $cname"
fi
done
3. Automated scanning with subjack
# Automated takeover detection tool:
./subjack -w subdomains.txt -t 50 -timeout 30 -ssl \
-c fingerprints.json -v
# fingerprints.json: Signatures for all known services
# Result: List of vulnerable subdomains!
4. Nuclei Templates for Subdomain Takeover
nuclei -l subdomains.txt -t nuclei-templates/takeovers/ -v
5. Manual Check
# CNAME pointing to unknown service → Send HTTP request:
curl -v https://staging.company.com
# Response: "No such app", "NoSuchBucket", "404 Not Found" → CHECK!
# Is the service still registered? Can I take over the claim?
6. Subdomain takeover proof (ethical)
<!-- Harmloser Proof of Concept - nur Nachweis der Möglichkeit! -->
<html><body>
[SECURITY RESEARCH] Subdomain takeover possible here.
Contact: security@company.com
</body></html>
<!-- Kein Cookie-Diebstahl! -->
Mitigation Measures
1. Immediate Action: Delete DNS entries during service teardown!
Process checklist for deleting a cloud resource:
- Delete service/app → IMMEDIATELY delete DNS CNAME entry!
- Delete S3 bucket → Delete CNAME record
- Delete Azure app → Remove custom domain from DNS
- Shut down staging/test environment → Clean up DNS records
> Problem: Teams delete the service but forget about DNS! DNS management must be part of the offboarding process.
2. Regular DNS Audits
Monthly Audit: Check all CNAMEs—do they point to active services? (Can be automated with subjack or nuclei)
DNS Monitoring Services:
- SecurityTrails: Monitor DNS changes
- Passive DNS (CIRCL): Historical DNS data
- CT Log Monitoring (certspotter): new certificates for subdomains
3. Use Ownership Verification in Cloud Services
Many cloud services require ownership verification:
- Azure: "Custom Domain Verification" (TXT record in DNS)
- AWS CloudFront: Certificate Validation
- GitHub Pages: CNAME + Repository Ownership
> If a service requires ownership verification: A takeover requires control over both DNS AND the service → more difficult! However: Not all services check ownership!
4. DNS Inventory in Asset Management
Inventory ALL DNS entries:
- Which subdomain points to which cloud service?
- Who is the owner/responsible party?
- Expiration date of the underlying service contract?
Tools for DNS Inventory:
- Cloudflare, Route53, Azure DNS: API queries possible
- Automated checks in CI/CD: new deployment → validate DNS
5. Automated Takeover Detection in CI/CD
# GitHub Actions / GitLab CI:
- name: Check for subdomain takeovers
run: |
nuclei -l dns/cnames.txt -t takeovers/ -severity critical,high
# → Daily scan of all known CNAMEs
# → CI failure if new takeover risk detected!