Research2026-03-217 min read

Subdomain Takeover: The Forgotten DNS Records Hackers Love

When companies decommission services but forget to clean up DNS records, attackers can claim those subdomains. Here is how it works and how to prevent it.

Subdomain takeover happens when a DNS record points to an external service that no longer exists. The subdomain is still live, still resolving, still trusted by browsers and users, but the service behind it is gone. Anyone who claims that service gets control of your subdomain.

This is not a theoretical attack. It is one of the most reported vulnerability classes on bug bounty platforms. HackerOne alone has published hundreds of subdomain takeover reports, with payouts ranging from $500 to $10,000 per finding. The issue affects companies of every size, from startups with a handful of subdomains to enterprises managing thousands of DNS records across multiple providers.

The root cause is simple: companies provision services, create DNS records to point to them, and then decommission the services without cleaning up the DNS. The dangling record becomes a liability.

What makes a subdomain vulnerable

A subdomain is vulnerable to takeover when three conditions are met simultaneously. The DNS record (usually a CNAME) points to an external service. The external service has been deprovisioned or was never claimed. The service provider allows new users to register the same hostname.

Here is a concrete example. Your company creates blog.company.com and sets up a CNAME record pointing to company-blog.herokuapp.com. Six months later, the marketing team switches to a different blogging platform and deletes the Heroku app. But nobody removes the CNAME record from DNS.

# DNS lookup for blog.company.com
$ dig blog.company.com CNAME

;; ANSWER SECTION:
blog.company.com.    300    IN    CNAME    company-blog.herokuapp.com.

# But the Heroku app no longer exists
$ curl https://company-blog.herokuapp.com
# "No such app" or "There is no app configured at that hostname"

Now any attacker can create a new Heroku app named company-blog on their own account and serve whatever content they want on blog.company.com.

Services most commonly exploited

Not all hosting providers are equally vulnerable. The risk depends on whether the provider allows new users to claim hostnames that were previously used. Here are the services most frequently involved in subdomain takeover reports:

ServiceCNAME PatternTakeover Fingerprint
GitHub Pagesusername.github.io"There isn't a GitHub Pages site here"
Herokuapp.herokuapp.com"No such app"
AWS S3bucket.s3.amazonaws.com"NoSuchBucket"
Azureapp.azurewebsites.netDefault Azure 404 page
Shopifyshops.myshopify.com"Sorry, this shop is currently unavailable"
Netlifysite.netlify.appNetlify "Not Found" page
FastlyFastly CDN"Fastly error: unknown domain"

AWS CloudFront, Zendesk, Tumblr, WordPress.com, and Cargo are also frequently reported as takeover-eligible depending on configuration.

Step-by-step attack scenario

Let us walk through a complete subdomain takeover from reconnaissance to exploitation.

Step 1: Enumerate subdomains. The attacker uses DNS enumeration tools to discover all subdomains of the target domain. Certificate Transparency logs, DNS brute-forcing, and search engine scraping are all effective techniques.

# Enumerate subdomains using subfinder
$ subfinder -d company.com -silent
www.company.com
app.company.com
api.company.com
blog.company.com
staging.company.com
docs.company.com
old-marketing.company.com

Step 2: Check CNAME records. For each subdomain, the attacker resolves CNAME records and checks if the target service still exists.

# Check for dangling CNAMEs
$ dig old-marketing.company.com CNAME +short
company-mktg.s3-website-us-east-1.amazonaws.com

$ curl -s http://company-mktg.s3-website-us-east-1.amazonaws.com
<Code>NoSuchBucket</Code>
<Message>The specified bucket does not exist</Message>

Step 3: Claim the resource. The attacker creates an S3 bucket with the exact name company-mktg in the same region. They upload a website and enable static hosting.

# Attacker creates the bucket
$ aws s3 mb s3://company-mktg --region us-east-1
$ aws s3 website s3://company-mktg --index-document index.html
$ echo '<h1>Controlled by attacker</h1>' > index.html
$ aws s3 cp index.html s3://company-mktg/ --acl public-read

Step 4: Control the subdomain. Now old-marketing.company.com serves the attacker's content. The browser treats it as a legitimate part of company.com. The SSL certificate, cookies, and user trust all apply.

Real-world impact

Subdomain takeover is not just about serving a defacement page. The consequences are far more severe because the attacker controls a subdomain under your domain.

Cookie theft

If your application sets cookies on .company.com (with a leading dot, meaning all subdomains), the attacker can read session cookies from the taken-over subdomain. This leads directly to account takeover.

Credential phishing. The attacker hosts a perfect replica of your login page on the controlled subdomain. Since the URL is login.company.com and the browser shows a valid certificate, users have no reason to suspect anything. Password managers may even autofill credentials.

Email spoofing. If the taken-over subdomain has SPF or DKIM records, or if the parent domain's SPF includes it, the attacker can send emails that pass authentication checks. Emails from noreply@marketing.company.com look completely legitimate.

CORS bypass. If your API trusts all subdomains via CORS (a common configuration, as discussed in our CORS article), the attacker can make authenticated API requests from the taken-over subdomain and read responses.

How to detect dangling records

Detection requires three steps: enumerate all subdomains, resolve their DNS records, and check whether the target services still exist.

DNS enumeration. Start with passive sources. Certificate Transparency (CT) logs provide a comprehensive list of subdomains for which SSL certificates have been issued. Tools like subfinder, amass, and crt.sh aggregate these sources.

# Query Certificate Transparency logs
$ curl -s "https://crt.sh/?q=%.company.com&output=json" \
  | jq -r '.[].name_value' \
  | sort -u

# Enumerate with multiple sources
$ subfinder -d company.com -all -silent | sort -u > subdomains.txt
$ wc -l subdomains.txt
247 subdomains.txt

CNAME resolution. For each subdomain, resolve its CNAME chain and check the final target. A CNAME that resolves to a known hosting provider but returns an error page is a strong indicator of a takeover opportunity.

# Bulk CNAME check
$ cat subdomains.txt | while read sub; do
    cname=$(dig +short CNAME "$sub" 2>/dev/null)
    if [ -n "$cname" ]; then
      echo "$sub -> $cname"
    fi
  done | tee cname-records.txt

# Look for known vulnerable patterns
$ grep -iE "herokuapp|s3.amazonaws|azurewebsites|github.io|netlify" cname-records.txt

Automated scanning. Tools like nuclei with takeover templates and subjack can automate the process of checking each CNAME against known fingerprints.

How to prevent subdomain takeover

Prevention is straightforward but requires discipline. The challenge is not technical complexity; it is organizational process.

Remove DNS records when decommissioning services. This is the single most important action. When you stop using a service, delete the CNAME (or A record) before or at the same time as deprovisioning the service. Make DNS cleanup a mandatory step in your decommission checklist.

Audit DNS records regularly. Schedule monthly or quarterly reviews of all DNS records. For each CNAME, verify that the target service still exists and is under your control. Automate this with a script that resolves all CNAMEs and flags any that return error pages.

Use DNS monitoring. Services like Recon0x, DNSMonitor, or custom scripts can continuously monitor your DNS records and alert you when a CNAME target becomes unreachable. This catches dangling records before attackers find them.

Restrict cookie scope. Avoid setting cookies on the bare domain with a leading dot (e.g., .company.com). Instead, set cookies on the specific subdomain that needs them (e.g., app.company.com). This limits the blast radius if a subdomain is compromised.

Use TXT records for ownership verification. Some providers (like GitHub Pages) now require you to verify domain ownership before serving content. Enable these verification mechanisms wherever available.

How Recon0x detects subdomain takeover

The Recon0x quick scan includes a subdomain takeover check as one of its 18 security assessments. Here is what it does during a scan:

First, it enumerates subdomains using Certificate Transparency logs and DNS resolution. Then, for each subdomain with a CNAME record, it resolves the full chain and checks the final target against a database of known vulnerable service fingerprints. If the target returns an error pattern matching a deprovisioned service (like "NoSuchBucket" for S3 or "No such app" for Heroku), it flags the subdomain as vulnerable.

The scan also checks for less obvious patterns: A records pointing to IP addresses that no longer respond, MX records for subdomains that point to decommissioned mail services, and NS delegations to nameservers the company no longer controls.

Each finding includes the exact CNAME chain, the vulnerable service, the fingerprint that was matched, and clear remediation steps (typically: remove the DNS record).

Scan your subdomains for free

Run a free security scan on your domain. Discover dangling DNS records before attackers do.

Get your free scan

Sources

  • OWASP: Subdomain Takeover
  • HackerOne Hacktivity: Subdomain Takeover Reports
  • Can I Take Over XYZ? (github.com/EdOverflow/can-i-take-over-xyz)
  • A Guide to Subdomain Takeovers (0xpatrik.com)
  • Certificate Transparency (certificate.transparency.dev)
  • MDN Web Docs: HTTP Cookies (Domain attribute)