DevOps 5 min read 962 words

Counterfeit TLS certificates for Google after hijacking three country-code domains

ES
Counterfeit TLS certificates for Google after hijacking three country-code domains

Google has explained on its blog that attackers managed to obtain valid HTTPS certificates for several Google domains and for “several leading global brands and widely used online services”. The most striking part is that no certificate authority failed and none of Google’s systems were compromised: the attackers hijacked the registries of three country-code domains, .gh (Ghana), .sl (Sierra Leone) and .as (American Samoa), and everything else followed from there.

I found it a good reminder that HTTPS security depends on something as unglamorous as DNS, and that there are a couple of things anyone with a domain can do.

How you get a certificate without breaking anything

To issue a certificate, a certificate authority has to check that whoever requests it controls the domain. That’s domain control validation (DCV), and it’s almost always automatic: publish a TXT record in DNS, serve a file at a specific HTTP path… That’s how Let’s Encrypt works, and it’s what has made almost the entire web encrypted today.

The problem is that this check trusts whatever DNS says. If you control a domain’s DNS, even briefly, you can prove you “control” the domain.

flowchart LR
    A["ccTLD registry · compromised"] --> B["Nameserver change · and DNS records"]
    B --> C["DCV check · passed"]
    C --> D["Valid certificate · issued by a legitimate CA"]
    D --> E["Domain · impersonation"]

That’s what happened here. With control of the .gh, .sl and .as registries, the attackers changed the nameserver delegation and DNS records of specific domains under those TLDs (Google hasn’t said which). The certificate authorities ran their checks, DNS answered what the attackers wanted, and the certificates were issued. Google says so plainly: “we have no reason to believe the Certification Authorities (CAs) that issued the impacted certificates did anything wrong”.

How it was detected and what Chrome did

This is where you see what Certificate Transparency (CT) is for. For years now, every certificate Chrome trusts has had to be published in public, append-only logs that anyone can query. Chrome rejects a certificate issued in secret.

Google first blocked the certificates for its own domains through CRLSets, Chrome’s mechanism for revoking certificates without waiting for the slow official revocation process. Then, going through the CT logs, it found certificates from other organizations affected by the same attacks, blocked those as well and notified whoever it could.

The incident is reminiscent of DigiNotar in 2011, when fake certificates were issued for google.com and more than 200 domains and used to spy on around 300,000 people in Iran. The big difference is that back then the certificate authority itself was compromised, and Certificate Transparency didn’t exist yet: it was created precisely in response to cases like that one.

What Google recommends to domain owners

What I liked most about the notice is that it doesn’t stop at “Chrome already protects you”. It says you shouldn’t rely only on the browser, because they can’t guarantee they’ve found every affected domain and because Chrome’s blocks don’t protect people using other browsers or clients. And it recommends two things.

Monitor Certificate Transparency logs

If someone issues a certificate for your domain, it will show up in the CT logs. There are services that alert you, and for a quick look crt.sh is enough:

curl -s "https://crt.sh/?q=antoniocortes.com&output=json" \
  | jq -r '.[] | "\(.not_before) \(.issuer_name)"' | sort | tail

I tried it with this blog: 135 certificates, all from Let’s Encrypt, which is what Netlify uses. If one from another authority ever appeared, I’d know something was wrong. Google stresses monitoring all your domains, including parked or regional ones, which tend to be the forgotten ones.

Publish restrictive CAA records

A CAA record (Certification Authority Authorization) is a DNS record where you state which authorities may issue certificates for your domain. Authorities are required to check it before issuing:

antoniocortes.com.  CAA  0 issue "letsencrypt.org"
antoniocortes.com.  CAA  0 issuewild ";"
antoniocortes.com.  CAA  0 iodef "mailto:security@example.com"

With this, only Let’s Encrypt could issue certificates, nobody could issue wildcards, and rejected attempts would be reported to that address. Google, for example, only allows its own authority (0 issue "pki.goog").

You have to be honest about its limits, and Google is: CAA prevents nothing during an active DNS hijack, because the attacker controls that record too. Its value lies in what happens afterwards. Authorities can reuse a completed validation for a while, so an attacker who validated the domain while controlling DNS could keep requesting certificates after you get it back. A restrictive CAA, especially one tied to a specific ACME account and validation method with the accounturi and validationmethods extensions, closes that door.

While writing this I checked that this domain has no CAA record at all. With a service like Netlify, which manages certificates for you, tying CAA to an ACME account isn’t practical, because the account isn’t yours. But restricting issuance to Let’s Encrypt is, and it costs nothing.

What I take away

HTTPS’s chain of trust is only as strong as its weakest link, and here the weak link was somewhere almost nobody looks: country-code domain registries, sometimes run with far fewer resources than the big ones. If your domain hangs off one of them, you depend on their security as much as your own.

I also think it’s a good demonstration that Certificate Transparency works: without those public logs, Google would hardly have found the other organizations’ certificates. And it fits with what the CA/Browser Forum has been pushing for a while: ever shorter certificates (by 2029 they’ll last 47 days at most) and less time to reuse validations, so that an incident like this leaves less behind.

The practical part is short: monitor the CT logs for your domains and publish a CAA record saying who can issue. It takes five minutes.