Subdomain Takeover: How Dangling DNS Records Put Your Laravel App at Risk
Dangling DNS records are one of the most overlooked attack vectors in Laravel deployments. Learn how subdomain takeover works, why deprovisioned cloud resources create exploitable gaps, and how to protect your application.
Your DNS zone file is a map of your infrastructure. Every record in it points to something: a server, a CDN, a cloud service, a third-party platform. But what happens when the thing on the other end disappears and the DNS record stays?
That is a dangling DNS record, and it is one of the most overlooked, most exploitable vulnerabilities in modern web deployments. For Laravel teams spinning up staging environments, microservices, and client demos on cloud infrastructure, the risk is real and growing.
This post breaks down how subdomain takeover attacks work, why Laravel deployments are particularly prone to creating dangling records, and what you can do to prevent them.
What Is a Subdomain Takeover?
A subdomain takeover happens when an attacker gains control of a subdomain that belongs to your organisation. The attack does not involve breaking into your DNS provider or compromising your registrar. It is simpler than that.
Here is the typical sequence:
- Your team creates
staging.yourapp.comand adds a CNAME record pointing to a cloud resource, for exampleyourapp-staging.herokuapp.comoryourapp-staging.s3.amazonaws.com - Months later, the staging environment is decommissioned. The Heroku app is deleted, or the S3 bucket is removed
- Nobody removes the CNAME record from your DNS zone
- An attacker discovers the dangling CNAME (this is trivially easy to automate)
- The attacker creates a new resource on the same cloud platform with the matching name
- Your DNS record now resolves to the attacker's resource. They control content served on your subdomain
The attacker did not hack anything. They simply filled a gap that your team left open.
How Dangling DNS Records Happen
Dangling records are almost always the result of process gaps, not technical failures. Infrastructure gets decommissioned, but DNS cleanup is not part of the decommissioning workflow. Here are the most common scenarios.
Deprovisioned Cloud Resources
This is the most frequent cause. Your team spins up an AWS Elastic Beanstalk environment, an Azure App Service, or a Google Cloud Run service for a feature branch, a demo, or a staging environment. A CNAME record is created to map a subdomain to the cloud endpoint. When the resource is later terminated, the DNS record remains.
Cloud providers do not delete your DNS records when you delete their resources. That is your responsibility.
Cancelled Third-Party Services
SaaS tools often require you to create a CNAME record for custom domain mapping. Landing page builders, documentation platforms, email marketing tools, status page services. When you cancel the subscription or stop using the service, the CNAME record pointing to their infrastructure stays in your zone file.
Many of these platforms allow new users to claim custom domain mappings, which means an attacker can sign up for the same service and claim your subdomain.
Deleted S3 Buckets and Blob Containers
S3 bucket names are globally unique. If you create a bucket called assets.yourapp.com, map a CNAME to it, and then delete the bucket, anyone in the world can create a new bucket with that same name. Your CNAME now points to their bucket, and they control what gets served on your subdomain.
Azure Blob Storage, Google Cloud Storage, and similar services have comparable risks.
Expired or Migrated Infrastructure
IP address changes during cloud migrations are another common source. If you migrate from one hosting provider to another and your old A records still point to the previous provider's IP range, those IPs may be reassigned to another customer. Your DNS record now points to someone else's server.
Real-World Attack Scenarios
Subdomain takeover is not theoretical. It has been exploited against major organisations, and the attack surface is expanding.
Credential Harvesting via Phishing
An attacker takes over accounts.yourapp.com and hosts a login page that mirrors your real application. Because the domain is legitimate (it is your actual subdomain), users have no reason to be suspicious. Browser address bars show your domain. SSL certificates can be provisioned via Let's Encrypt for the subdomain. The phishing page collects credentials and forwards users to the real login page.
Cookie Theft and Session Hijacking
This is where subdomain takeover gets particularly dangerous for Laravel applications. If your Laravel app sets cookies on the parent domain (e.g., .yourapp.com), any subdomain can read those cookies. An attacker controlling anything.yourapp.com can read session cookies, CSRF tokens, and any other cookies scoped to the parent domain.
For Laravel apps using session-based authentication, this means an attacker can potentially hijack active user sessions by reading the laravel_session cookie from a taken-over subdomain.
Malware Distribution
An attacker serves malware from your subdomain, leveraging your domain's reputation score. Email filters, web proxies, and endpoint protection tools are less likely to block downloads from an established, reputable domain. Your domain becomes the delivery mechanism for someone else's payload.
SEO Poisoning
Attackers host content on your subdomain to benefit from your domain authority. They can inject backlinks, host spam content, or redirect traffic to affiliate schemes. This degrades your domain's search reputation over time.
How to Audit Your DNS Records
A DNS audit is the first step toward eliminating dangling records. Here is a systematic approach.
Step 1: Export Your Complete Zone File
Pull a full export of every DNS record for every domain you manage. Check your primary DNS provider, but also check for records managed through cloud providers like Route 53, Cloudflare, or Azure DNS. Teams often have records scattered across multiple providers.
Step 2: Inventory Every CNAME and A Record
For each CNAME record, resolve the target and verify that:
- The target resource exists and is under your control
- The target responds with your expected content, not a cloud provider default page or error
For each A record, verify that:
- The IP address belongs to infrastructure you control
- The server at that IP is responding and serving your content
Step 3: Check for Known Vulnerable Patterns
Certain DNS patterns are high-risk indicators for takeover vulnerability:
# These patterns suggest potentially dangling records
staging.yourapp.com CNAME yourapp-staging.herokuapp.com # Heroku
docs.yourapp.com CNAME yourapp.readme.io # ReadMe
status.yourapp.com CNAME yourapp.statuspage.io # Statuspage
demo.yourapp.com CNAME yourapp.s3.amazonaws.com # S3
cdn.yourapp.com CNAME d1234abcdef.cloudfront.net # CloudFront
Resolve each one. If you get an NXDOMAIN response, a "NoSuchBucket" error, a "No such app" page, or a generic cloud provider 404, you likely have a dangling record.
Step 4: Verify with HTTP Requests
DNS resolution alone is not enough. Make actual HTTP requests to each subdomain and inspect the response:
# Check for dangling records
for subdomain in $(dig +short yourapp.com AXFR | grep CNAME | awk '{print $1}'); do
echo "Checking $subdomain"
curl -s -o /dev/null -w "%{http_code} %{redirect_url}" "https://$subdomain"
echo ""
done
Look for unexpected status codes, redirect chains to cloud provider sign-up pages, or content you do not recognise.
Step 5: Automate and Schedule
A one-time audit is not sufficient. Infrastructure changes happen continuously. New subdomains get created, old resources get decommissioned. You need continuous monitoring.
This is exactly what StackShield does. As part of its 30+ security checks, StackShield continuously monitors your DNS records for dangling CNAMEs, orphaned A records, and other DNS misconfigurations that indicate takeover risk. Every scan checks that your DNS records resolve to resources you actually control.
Prevention Strategies
Detecting dangling records after the fact is important, but preventing them from being created in the first place is better.
1. Make DNS Cleanup Part of Your Decommissioning Workflow
Every infrastructure teardown checklist should include a DNS cleanup step. When you delete a cloud resource, remove the corresponding DNS record in the same change request. Treat them as a single atomic operation.
For Laravel teams using infrastructure-as-code tools like Terraform or Pulumi, define your DNS records alongside your infrastructure resources. When the resource is destroyed, the DNS record is automatically removed.
2. Use Infrastructure-as-Code for DNS
Managing DNS records through a web console is error-prone. Records get created ad hoc and forgotten. Define all DNS records in version-controlled configuration files:
# Terraform example: DNS record tied to the resource lifecycle
resource "aws_route53_record" "staging" {
zone_id = aws_route53_zone.main.zone_id
name = "staging.yourapp.com"
type = "CNAME"
ttl = 300
records = [aws_elastic_beanstalk_environment.staging.cname]
}
When aws_elastic_beanstalk_environment.staging is destroyed, Terraform knows to remove the Route 53 record too.
3. Restrict Wildcard DNS Records
Wildcard DNS records (*.yourapp.com) are particularly dangerous. A single wildcard CNAME pointing to a deprovisioned resource means every possible subdomain is vulnerable to takeover, not just one specific subdomain.
Avoid wildcard records unless absolutely necessary. If you must use them, ensure the target resource is permanent and under your direct control.
4. Implement Domain Verification Where Possible
Some cloud providers support domain ownership verification before allowing custom domain mappings. Enable this wherever available. It adds a step when setting up custom domains but prevents attackers from claiming your subdomain on their platform.
5. Monitor Certificate Transparency Logs
Certificate Transparency (CT) logs record every SSL certificate issued for your domain. If an attacker takes over a subdomain and provisions a certificate, it will appear in CT logs. Tools like crt.sh or Facebook's CT monitoring can alert you to unexpected certificate issuance.
6. Scope Cookies Tightly
For your Laravel application, restrict cookie scope to prevent subdomain takeover from escalating to session hijacking:
// config/session.php
'domain' => 'yourapp.com', // Do not use '.yourapp.com'
'secure' => true,
'same_site' => 'lax',
Using the exact domain instead of a wildcard domain (prefixed with a dot) prevents subdomains from accessing your application's cookies. This does not prevent subdomain takeover itself, but it limits the blast radius significantly.
How StackShield Detects Dangling Records
StackShield's DNS misconfiguration scanner checks for dangling records every time it scans your Laravel application. Here is what happens under the hood.
CNAME resolution chain validation. StackShield follows the full CNAME resolution chain for every subdomain associated with your domain. If any link in the chain resolves to an NXDOMAIN, a cloud provider error page, or an unclaimed resource endpoint, it flags the record as dangling.
Cloud provider fingerprinting. StackShield maintains a database of response signatures for major cloud providers. It recognises "NoSuchBucket" responses from S3, "No such app" from Heroku, "NXDOMAIN" patterns from Azure, and dozens of other indicators that a target resource has been deprovisioned.
Continuous monitoring. Unlike a one-time audit, StackShield rescans on your configured schedule (hourly, daily, weekly, or monthly). Infrastructure changes between audits are caught automatically.
Severity classification. Not all dangling records carry the same risk. A CNAME pointing to a claimable S3 bucket is critical severity. A CNAME pointing to an unresolvable internal hostname is lower severity. StackShield classifies findings so you can prioritise remediation.
If you are managing a Laravel application in production, run a free StackShield scan to check for dangling DNS records and 30+ other Laravel-specific security issues. It takes less than a minute and requires no code changes.
Key Takeaways
Subdomain takeover via dangling DNS records is a low-skill, high-impact attack that thrives on operational gaps. The vulnerability is not in your code or your framework. It lives in the space between your infrastructure and your DNS configuration.
For Laravel teams, the risk is amplified by the tendency to spin up subdomains for staging, demos, APIs, and admin tools, each one a potential dangling record when the resource behind it disappears.
The fix is straightforward:
- Audit your DNS records now. Identify and remove any records pointing to resources you no longer control
- Build DNS cleanup into your decommissioning workflows so dangling records stop being created
- Monitor continuously, because manual audits go stale the moment your infrastructure changes
- Scope your cookies tightly to limit the impact if a subdomain is compromised
- Use StackShield to automate detection of dangling records alongside your other Laravel security checks
DNS hygiene is not exciting work, but it is the kind of foundational security practice that prevents a trivial misconfiguration from becoming a serious breach.
Frequently Asked Questions
What is a subdomain takeover?
A subdomain takeover occurs when a DNS record (usually a CNAME) points to an external resource that no longer exists, such as a deprovisioned cloud VM, a deleted S3 bucket, or a cancelled SaaS service. An attacker can claim that orphaned resource and serve their own content on your subdomain, effectively hijacking part of your domain.
How do dangling DNS records get created?
Dangling DNS records are typically created when teams decommission infrastructure without cleaning up the corresponding DNS entries. Common causes include deleting a cloud load balancer or VM without removing its A or CNAME record, cancelling a third-party service like a CDN or landing page builder, removing an S3 bucket or Azure Blob container that was mapped to a subdomain, and shutting down a staging or demo environment while leaving the DNS intact.
Are Laravel applications specifically vulnerable to subdomain takeover?
Laravel applications are not inherently more vulnerable than other frameworks, but the typical Laravel deployment pattern creates risk. Laravel teams frequently provision subdomains for staging environments, Horizon dashboards, API gateways, documentation sites, and client demos. Each of these subdomains backed by a cloud resource is a potential dangling record if the resource is later removed without updating DNS.
How can I check if my domain has dangling DNS records?
You can manually audit by exporting all DNS records from your provider and resolving each CNAME and A record to verify the target resource still exists. Look for NXDOMAIN responses, cloud provider default pages, or "bucket not found" errors. For continuous monitoring, StackShield automatically detects dangling records as part of its 30+ Laravel-specific security checks, alerting you before an attacker can exploit them.
What is the worst-case impact of a subdomain takeover?
The worst-case impact includes serving phishing pages on your domain to steal user credentials, hosting malware that inherits your domain reputation, reading and setting cookies scoped to your parent domain (potentially hijacking user sessions on your main Laravel app), bypassing content security policies that trust your domain, and sending authenticated emails from your subdomain if SPF and DMARC are not tightly configured.
Related Security Terms
Related Articles
Laravel Debug Mode in Production: Why It's Dangerous and How to Fix It
Debug mode in production exposes stack traces, database credentials, environment variables, and internal paths. Learn exactly what it reveals, how attackers use it, and how to make sure it never reaches production.
SecurityOWASP Top 10 for Laravel: A Practical Guide
A hands-on mapping of every OWASP Top 10 (2021) category to specific Laravel vulnerabilities, with code examples of what goes wrong and how to fix it.
SecurityIs Your Laravel .env File Exposed? How to Check and Fix It
Your .env file contains database credentials, API keys, and encryption secrets. If it's accessible from the web, attackers already have everything they need. Here's how to check and fix it.
Compare StackShield
Security Checklists
Laravel Production Deployment Security Checklist
A comprehensive security checklist for deploying Laravel applications to production. Covers environment config, server hardening, access control, and monitoring.
20 itemsLaravel API Security Checklist
Secure your Laravel API endpoints against common vulnerabilities. Covers authentication, input validation, rate limiting, and response security.
Stay Updated on Laravel Security
Get actionable security tips, vulnerability alerts, and best practices for Laravel apps.