DEV Community

Cover image for GoDaddy gave my domain to a stranger: I simulated the attack on my own infra and learned how exposed I really was
Juan Torchia
Juan Torchia

Posted on • Originally published at juanchi.dev

GoDaddy gave my domain to a stranger: I simulated the attack on my own infra and learned how exposed I really was

GoDaddy gave my domain to a stranger: I simulated the attack on my own infra and learned how exposed I really was

It was 10pm and I was scrolling Hacker News when the post hit the top: GoDaddy had transferred a domain to someone who wasn't the owner. Score 610, 200+ comments, most of them saying "I moved to Cloudflare years ago" or "this is why you don't use GoDaddy". I closed the tab. And then I just sat there thinking.

I have six active domains. Three on Namecheap, two on Cloudflare Registrar, one on Porkbun. All connected to Railway or Vercel. All pointing at things that, if they go down, come crashing down on me.

My first reaction was the condescending nerd one: "I don't use GoDaddy, I'm fine." My second reaction, twenty minutes later, was the architect who knows that arrogance in security is the most expensive vulnerability. So I didn't cover the incident as news. I used it as an excuse to simulate the attack against my own infrastructure, document every step, and measure how far an attacker would have gotten before I even noticed.

My thesis, before diving in: the problem isn't GoDaddy specifically. It's that the DNS identity verification chain was designed in the '90s for a world where changing a record was a rare, manual event. Today, with automation, CI/CD, and registrar APIs that respond in milliseconds, that chain is wet paper. And nobody's redesigning it.


GoDaddy domain hijacking: what happened and why I took it personally

The case reported on HN described a classic social engineering vector combined with a support process that validated identity by email. The attacker didn't hack any system. They called (or wrote), presented fake documentation, and GoDaddy's internal process handled the transfer.

That's when I actually got angry. Because it's not a bug. It's a process working exactly as designed — and the design is the problem.

I went and reviewed the transfer processes for the three registrars I use. Here's what I found for an outbound domain transfer:

  • Namecheap: confirmation email to the registered address + authorization code (EPP). If the attacker has access to the email, the domain walks out in 5-7 days with zero additional friction.
  • Cloudflare Registrar: same as Namecheap, plus optional 2FA (which I had enabled on two of three domains, not all — embarrassing detail).
  • Porkbun: email + mandatory TOTP for transfers. The most resistant of the three.

The attack vector isn't the registrar. It's the email address associated with the registrar account.


How I simulated the attack: step by step with my own stack

I didn't break anything real. I used a test domain I have on Namecheap (juanchi-test-[hash].com, bought in January, never pointed at production) and documented every step as if I were an attacker with access to my Google Workspace email.

Phase 1: reconnaissance

# First thing an attacker would do: map the surface
whois juanchi-test-[hash].com

# Relevant output (anonymized):
# Registrar: Namecheap, Inc.
# Creation Date: 2025-01-15
# Registry Expiry Date: 2026-01-15
# Name Server: dns1.registrar-servers.com
# Name Server: dns2.registrar-servers.com
# DNSSEC: unsigned  <-- this matters, we'll get to it

# Registrant email was redacted (WhoisGuard active)
# But the registrar shows up — first useful data point for the attacker
Enter fullscreen mode Exit fullscreen mode

WHOIS gave me the registrar. With that, an attacker knows who to call. WhoisGuard hides the technical contact's email, but doesn't hide the registrar. It's like hiding your name on the door but leaving the apartment number visible.

Phase 2: the real vector — compromise the email first

Here's the insight that made me most uncomfortable. An attack on a domain doesn't start at the registrar. It starts at the email.

# Checked what MX records my test domain had
dig MX juanchi-test-[hash].com

# And what SPF/DKIM the email domain I use for the registrar had
dig TXT juanchi-dev.com | grep -E "v=spf|DKIM"

# Result: SPF configured, DKIM active on Cloudflare
# But the weak point isn't the configuration — it's account recovery
Enter fullscreen mode Exit fullscreen mode

Google Workspace has SMS recovery. My phone number is in the profile. If someone does SIM swapping, they have my email. If they have my email, they have all my Namecheap domains and two of three on Cloudflare (the one without 2FA enabled).

That was the moment I understood I was just as vulnerable as any GoDaddy user. My attacker just needed one extra step first.

Phase 3: what Namecheap "support" requires for an emergency transfer

I didn't call pretending to be anyone. I read Namecheap's public support documentation for domain recovery cases when you've "lost access to your email." Here's what they ask for:

  1. Photo of your ID document
  2. Last purchase invoice for the domain
  3. Description of the problem

That's it. No liveness check. No callback to the registered phone number. No independent second factor. If an attacker has a photo of my ID (which exists on LinkedIn, at conferences, in a million places), a convincing fake invoice, and email access — or doesn't need the email because support can override — the domain can walk.

This process exists at almost every registrar. Because it was designed for the legitimate case of "I forgot my password and changed my email." Not for a sophisticated attacker.

Phase 4: what would happen next — the damage to my Railway/Vercel stack

Once the domain is transferred, the attacker controls DNS. Here's what they could do against my Railway and Vercel infra:

# Scenario: attacker has domain juanchi.dev
# Step 1: changes the A record to their own server
# Time for the change to propagate: 30 min to 48h depending on TTL

# My current TTLs (measured before the experiment):
dig juanchi.dev | grep TTL
# TTL: 300 seconds — propagation in 5 minutes

# Step 2: request SSL certificate with Let's Encrypt
# ACME HTTP-01 or DNS-01 challenge — trivial with domain control
# Time: under 2 minutes

# Step 3: mount a reverse proxy pointing at my Railway deployment
# Or just an identical phishing page
# With a valid cert and the real domain, the browser shows nothing unusual
Enter fullscreen mode Exit fullscreen mode

The 300-second TTL I had configured for performance would have given me a five-minute detection window after the change. Way too short.

This connects directly to what I documented in the Vercel breach post — when the deployment infrastructure is compromised, or the domain feeding it is compromised, the damage isn't technical. It's trust. And trust doesn't roll back.


The mistakes I found in my own configuration

I'm going to be specific because that's the most valuable part of this experiment. These are the real problems I had before simulating the attack:

Mistake 1: inconsistent 2FA across registrars

One domain on Cloudflare Registrar without 2FA enabled. No excuse. Fixed it in ten minutes during the experiment.

Mistake 2: DNSSEC disabled on all my domains

# Quick DNSSEC check
dig DS juanchi.dev @8.8.8.8
# Empty response = DNSSEC not configured

# With DNSSEC active, an attacker who modifies DNS records
# generates responses that resolvers validate and reject
# Not bulletproof, but it adds real friction
Enter fullscreen mode Exit fullscreen mode

DNSSEC is annoying to set up. Cloudflare does it in one click. Namecheap supports it but the UI is terrible. I had it enabled on none of them. Now I have it on four of six domains (the two on Porkbun are still pending — I'm migrating them this week).

Mistake 3: no alerts for DNS record changes

I had zero alerting to detect changes to my A, CNAME, or NS records. An attacker could have changed the NS record and I would have found out when a user messaged me that the site was down — or worse, that something was off.

I fixed this with a simple script running on a Railway cron job:

// monitor-dns.ts — runs every 5 minutes on Railway
// Sends a Telegram alert if any record changes

import { Resolver } from 'node:dns/promises';

const resolver = new Resolver();
// Using different resolvers to detect cache divergence
resolver.setServers(['8.8.8.8', '1.1.1.1']);

const CRITICAL_DOMAINS = [
  { domain: 'juanchi.dev', type: 'A', expectedValue: process.env.IP_PROD },
  { domain: 'api.juanchi.dev', type: 'CNAME', expectedValue: 'my-app.railway.app' },
];

async function checkRecords() {
  for (const { domain, type, expectedValue } of CRITICAL_DOMAINS) {
    try {
      const result = await resolver.resolve(domain, type as 'A' | 'CNAME');
      const currentValue = result[0];

      if (currentValue !== expectedValue) {
        // Something changed — immediate alert
        await notifyTelegram(
          `⚠️ DNS CHANGED\nDomain: ${domain}\nExpected: ${expectedValue}\nActual: ${currentValue}`
        );
      }
    } catch (error) {
      // Domain doesn't resolve — that's also an alert
      await notifyTelegram(`🚨 DNS NOT RESOLVING: ${domain}`);
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Simple. Runs on Railway with a cron job. I got one false positive alert on the first day because Railway rotated a deployment IP — which was, ironically, exactly the kind of detection I was going for.

Mistake 4: the registrar recovery email was the same as my work email

If someone compromised my Google Workspace account, they had access to everything. I moved the registrar accounts to a dedicated email — no alias, different password generated in Bitwarden, hardware key (YubiKey) as the second factor.

This is especially relevant given the Bitwarden CLI supply chain attack I documented last week — the trust surface isn't just the password manager, it's everything that password manager protects.


The gotchas nobody mentions in "protect your domains" posts

Transfer lock doesn't save you from social engineering

Every registrar has a "transfer lock" — it blocks outbound transfers. But social engineering doesn't need a transfer. It needs to change the NS records, which on most registrars lives in the same panel as the transfer lock and requires exactly the same level of access.

Registry Lock actually helps, but it's for enterprises

There's something called Registry Lock (distinct from Registrar Lock) that requires out-of-band verification for any change, including NS updates. Verisign and other registries offer it for .com. It costs $100-$300/year per domain. Not for personal blogs, but if you have a domain that's critical to your business, it's worth the conversation.

DNSSEC doesn't protect against registrar-level hijacking

If the attacker already controls the registrar, they can change the DS record (the "anchor" for DNSSEC) along with the NS records. DNSSEC protects against attacks at the resolution layer (cache poisoning). It doesn't protect you if the attacker has access to the registrar panel.


FAQ: GoDaddy domain hijacking and how to protect your domains

Does this only happen with GoDaddy or can it happen with any registrar?

Any registrar. GoDaddy has more reported cases because it has more users, but the email + document identity verification process for account recovery is practically universal. Namecheap, Google Domains (now Squarespace), Name.com — they all have similar processes. The problem is systemic, not vendor-specific.

Is enabling 2FA on the registrar enough?

Necessary but not sufficient. 2FA protects direct login. But if the registrar's account recovery process accepts "email + photo ID" as a fallback (many do), 2FA has a bypass via support. The most robust protection combines strong 2FA (TOTP or hardware key) + a dedicated email for the registrar account + active monitoring for DNS changes.

What is Registry Lock and is it worth paying for?

Registry Lock is an additional protection layer implemented by the registry (Verisign for .com, for example) that requires out-of-band verification for any change operation. The registrar can't process an NS change or a transfer without going through a manual registry process. It costs $100-$300/year per domain and makes sense for domains that generate direct revenue or have high production impact.

Does DNSSEC solve this?

Partially. DNSSEC protects against cache poisoning and attacks at the resolution layer. It doesn't protect you if the attacker already has access to the registrar panel — because they can change the DS record alongside the NS records. It's a valid defense layer, but it's not the final shield against domain hijacking.

How long does a malicious DNS change take to propagate?

It depends on the configured TTL. With a TTL of 300 seconds (5 minutes, common in performance-tuned configs), an attacker has effective control of traffic in under 10 minutes after changing the record. With a TTL of 3600 (1 hour), you get a longer detection window but resolvers also cache the legitimate value longer. There's no perfect answer — low TTL accelerates both the attack and the recovery.

Can Railway or Vercel do anything if the domain gets hijacked?

Not much. If the domain stops pointing to the Railway or Vercel deployment, the deployment stays alive but traffic stops arriving. You can make the app respond from the Railway internal URL (*.railway.app) while you sort out the domain, but users hitting the compromised domain will see whatever the attacker has mounted — with a valid SSL certificate and the real domain in the browser bar. Vercel and Railway are not part of the domain custody chain.


What changed in my infra after this experiment

Concrete, no fluff:

  1. YubiKey 2FA on all registrars — not just TOTP, hardware key as second factor wherever it's supported
  2. Dedicated email for registrars — isolated from Google Workspace, with its own domain that isn't registered at any of the registrars it protects
  3. DNSSEC enabled on four of six domains — the remaining two are moving to Cloudflare Registrar this week
  4. DNS monitor on Railway — cron every 5 minutes, Telegram alert within 10 minutes of any divergence
  5. TTL increased on critical domains — from 300 to 900 seconds. The slower propagation trade-off is worth the wider detection window
  6. Audit of the account recovery process — read the support documentation for each registrar to understand what bypasses exist and what mitigations apply

The attack surface didn't disappear. But the friction for an attacker increased considerably, and my detection time dropped from "when someone messages me that the site is acting weird" to "ten minutes after the change."

The uncomfortable part of all this is that none of these measures required the GoDaddy incident to implement. I knew about them. I had them on my backlog. And I did them on a Saturday night after reading a post on HN.

That says more about how we prioritize security than anything GoDaddy could have done wrong.

If you want to check how exposed your current stack is, start with the registrar's email account. Not the registrar panel. The email is the real entry point, and if that email falls, everything else follows.


This article was originally published on juanchi.dev

Top comments (0)