A subdomain takeover lets an attacker serve content from your domain by claiming an abandoned cloud resource. This guide explains the mechanics, shows real-world examples, and gives you a concrete remediation and monitoring workflow.
Anay Pandya
1,408 words
Anay Pandya
Founder of ZeriFlow · 10 years fullstack engineering · About the author
Key Takeaways
Subdomain takeover is one of the most underestimated vulnerabilities in web security. It requires no code exploit, no brute-forcing, and no sophisticated tooling. An attacker finds a subdomain that points to a cloud resource nobody owns anymore, registers that resource, and immediately begins serving content from your domain. Victims see a fully trusted URL — staging.yourcompany.com, blog.yourcompany.com, api-old.yourcompany.com — that is now under attacker control.
The consequences range from phishing campaigns to cookie theft (depending on cookie scope) to reputational damage. HackerOne''s bug bounty data consistently lists subdomain takeovers as high-severity findings, with payouts frequently in the $1,000-$5,000 range — which means attackers are actively hunting for them on your domains right now.
Keep reading
Is your site actually secure?
Run a free check — 60 seconds
The vulnerability requires three conditions:
CNAME) pointing subdomain.yourdomain.com to an external service endpoint.The attack flow:
DNS lookup: staging.yourcompany.com
→ CNAME → yourcompany.github.io
→ yourcompany.github.io resolves to GitHub Pages IPs
→ GitHub: "No repository configured for yourcompany.github.io" → 404
Attacker creates GitHub account "yourcompany", creates a repository "yourcompany.github.io"
→ GitHub Pages now serves their content at yourcompany.github.io
→ staging.yourcompany.com now serves attacker contentThe attacker does not need access to your DNS — they only need access to the external platform, which is often free and open to registration.
GitHub Pages is the most commonly exploited vector. When a company shuts down a project or renames a GitHub organization, CNAME records pointing to orgname.github.io become vulnerable.
Indicators:
$ dig staging.example.com CNAME
staging.example.com. 300 IN CNAME example-staging.github.io.
$ curl -I https://example-staging.github.io
HTTP/2 404
# Response body: "There isn''t a GitHub Pages site here."If you see this 404 from GitHub, the subdomain is likely claimable.
Heroku apps have URLs like appname.herokuapp.com. When an app is deleted but the DNS CNAME pointing to it remains, anyone can create a new Heroku app with the same name:
subdomain.example.com → CNAME → example-prod-api.herokuapp.com
# App was deleted during a migration
# Attacker:
heroku create example-prod-api
# Now controls subdomain.example.comS3 static website hosting uses bucket names that must match the subdomain. If assets.example.com points to assets.example.com.s3-website-us-east-1.amazonaws.com and the bucket is deleted, any AWS user can create a bucket named assets.example.com:
assets.example.com → CNAME → assets.example.com.s3-website-us-east-1.amazonaws.com
# Bucket deleted
$ curl https://assets.example.com.s3-website-us-east-1.amazonaws.com
# Response: NoSuchBucket
# Attacker creates bucket named "assets.example.com" with public website hosting
# Now serves malicious JS files from assets.example.comThis is particularly dangerous for subdomains serving JavaScript files — the attacker can inject malicious scripts into every page that loads assets from that URL.
| Platform | Indicator | Risk Level |
|---|---|---|
| Azure App Service | azurewebsites.net endpoint returns error | High |
| Fastly | fastly.net CNAME, Fastly returns 500/503 | High |
| Netlify | netlify.app returns 404 | High |
| Ghost (Pro) | ghost.io CNAME, domain not claimed | Medium |
| Shopify | myshopify.com CNAME, shop deactivated | Medium |
| Zendesk | zendesk.com CNAME, help center removed | Medium |
| Tumblr | tumblr.com CNAME, blog deleted | Medium |
A comprehensive list of vulnerable services and their fingerprints is maintained at can-i-take-over-xyz.
Once an attacker controls a subdomain, several attack vectors open:
Phishing — The attacker creates a convincing login page at accounts.yourcompany.com or login.yourcompany.com. Users trust the domain. Password reuse and credential harvesting follow.
Cookie theft — Cookies set with Domain=.yourcompany.com (note the leading dot) are sent by the browser to all subdomains including the taken-over one. If your application sets session cookies this way, the attacker can harvest them.
XSS via asset injection — An attacker who controls static.yourcompany.com can serve malicious JavaScript that any page loading resources from that subdomain will execute.
CORS abuse — If your API allowlists *.yourcompany.com in its CORS policy, the attacker''s origin becomes a trusted CORS origin, enabling cross-origin requests to your API with victim credentials.
Email spoofing — Subdomain control can sometimes be used to pass SPF/DKIM checks if mail infrastructure uses that subdomain, enabling email spoofing from a trusted-looking address.
# Install
go install github.com/PentestPad/subzy@latest
# Scan a list of subdomains
subzy run --targets subdomains.txt
# Output vulnerable subdomains only
subzy run --targets subdomains.txt --vuln# Install nuclei
go install github.com/projectdiscovery/nuclei/v3/cmd/nuclei@latest
# Run subdomain takeover templates against a list
nuclei -l subdomains.txt -t ~/nuclei-templates/takeovers/
# Against a single target
nuclei -u https://staging.example.com -t ~/nuclei-templates/takeovers/go install github.com/haccer/subjack@latest
subjack -w subdomains.txt -t 100 -timeout 30 -ssl -c ~/go/pkg/mod/github.com/haccer/subjack@latest/fingerprints.jsonBefore you can scan for takeovers, you need a comprehensive list of your subdomains:
# subfinder
go install github.com/projectdiscovery/subfinder/v2/cmd/subfinder@latest
subfinder -d yourcompany.com -o subdomains.txt
# amass
go install github.com/owasp-amass/amass/v4/...@master
amass enum -d yourcompany.com -o subdomains.txt
# Certificate Transparency logs (free, no install needed)
curl "https://crt.sh/?q=%.yourcompany.com&output=json" | jq ''.[].name_value'' | sort -uThe fix depends on whether you still need the subdomain:
Delete the DNS record. This is the correct fix and the only permanent one:
# Via AWS Route 53 CLI
aws route53 change-resource-record-sets \\
--hosted-zone-id YOUR_ZONE_ID \\
--change-batch ''{
"Changes": [{
"Action": "DELETE",
"ResourceRecordSet": {
"Name": "staging.yourcompany.com",
"Type": "CNAME",
"TTL": 300,
"ResourceRecords": [{"Value": "yourcompany-staging.herokuapp.com"}]
}
}]
}''Re-create the resource at the cloud provider before deleting and recreating the DNS record:
GitHub provides domain verification that prevents others from claiming your organization''s domain:
yourcompany.com)Maintain a DNS inventory — keep a record of every DNS record and the resource it points to. When you decommission a cloud resource, the DNS record deletion should be part of the offboarding checklist.
Automate DNS record cleanup — use infrastructure-as-code (Terraform, Pulumi) where DNS records are created and destroyed together with their associated cloud resources. If the resource is deleted, the DNS record is deleted in the same terraform destroy.
# Terraform — DNS record tied to resource lifecycle
resource "heroku_app" "staging" {
name = "yourcompany-staging"
region = "us"
}
resource "aws_route53_record" "staging" {
zone_id = var.hosted_zone_id
name = "staging.yourcompany.com"
type = "CNAME"
ttl = 300
records = ["${heroku_app.staging.web_url}"]
}
# When heroku_app.staging is destroyed, aws_route53_record.staging goes with itUse short TTLs on CNAME records — a TTL of 300 seconds (5 minutes) means if a DNS record is compromised, propagation of the fix is fast.
Monitor for DNS changes — set up alerts when DNS records change unexpectedly. ZeriFlow monitors your DNS configuration continuously and alerts you via Slack, Discord, or email when records change or when new vulnerability indicators appear.
Quarterly subdomain audits — run your subdomain enumeration and takeover scan every quarter. Cloud infrastructure changes frequently, and a record that was safe six months ago may now point to a deleted resource.
ZeriFlow scans your DNS records as part of its 80+ security checks, identifying dangling CNAMEs and subdomain configurations that suggest takeover risk. Run a free scan at zeriflow.com and see your full DNS security picture in under 60 seconds.
Related resources
Website Vulnerability Scanner
Run a broader website security audit across headers, TLS, DNS, cookies, SEO, and disclosure checks.
Security Headers Checker
Check CSP, HSTS, X-Frame-Options, and other response headers.
SSL Checker
Review TLS certificate, HTTPS, and transport security signals.
DMARC Checker
Validate email authentication records for domain spoofing protection.
CSP Checker
Review Content-Security-Policy coverage and common gaps.
April 30, 2026
Best SAST Tools for Small Development Teams in 2026 (Free Included)
Monitor your security score
Schedule recurring scans and catch regressions after deployments.