Guest blog: Bypassing domain control verification with DNS response spoofing

labsdetectify

Our guest blogger and Detectify Crowdsource hacker Evgeny Morozov explains how he bypassed Detectify’s domain control verification by using DNS response spoofing. A big thank you to Evgeny for this very smart and cool workaround – it’s awesome to have researchers like you in our Crowdsource team!

 

Detectify doesn’t allow scanning a website until the user verifies that they control the domain. One of the verification methods is to add a DNS TXT record to the domain, containing a string provided by Detectify. When the user clicks Verify, Detectify performs a DNS query and checks for the magic string. Let’s see if it can be tricked into “verifying” a domain the user doesn’t actually control.

 

DNS spoofing background

DNS queries and responses are normally sent over UDP, so IP address spoofing makes it possible for an attacker to send a DNS response to the client that appears to come from the DNS server it queried. Of course, the client will only accept the response if it matches an outstanding query. In particular, the following fields must match:

  1. Source (DNS server) IP address
  2. Destination (DNS client) IP address
  3. Source (DNS server) port – always 53
  4. Destination (DNS client) port – the source port of the DNS request
  5. “Transaction ID” – a 16-bit number generated by the client
  6. “Questions” – essentially a copy of the DNS query

The source port, source IP and destination IP are known. The DNS “questions” can usually be guessed or, even better, copied from the real query if the attacker has access to it. The only unknown fields are the destination port and transaction ID.

 

Until about 9 years ago many DNS clients used a fixed or easily predictable source port or transaction ID (or both). Guessing one 16-bit number is entirely doable: there are only 65,536 possibilities and the attacker may be able to get several thousand fake response packets to the DNS client before the real response arrives. In July 2008 Dan Kaminsky revealed this issue (and some other related issues) and DNS implementations were quickly patched to use truly random transaction IDs and port numbers. The cryptographically secure fix, DNSSEC, is still being deployed, but 32 bits of entropy provides sufficient protection in practice, so this attack is obsolete today.

Or is it?

Verifying the verifier

I had a hunch that, to avoid any cached results, Detectify’s verifier may do its own DNS queries, rather than using only the operating system’s DNS resolver. If so, it may still use a predictable transaction ID or a small range of source ports.

 

To test this I set up a simple nameserver using dnsmasq for a domain I control and captured its traffic using tcpdump as I tried to verify it on the Detectify site multiple times. Opening the resulting capture file in Wireshark showed that there was indeed a DNS query directly from scanner.detectify.com. The source port looked random enough, but wait… where is the transaction ID?

 

Query capture

Well, this certainly simplifies things!

 

It’s zero! The transaction ID is zero every time and I know the exact query Detectify is sending, so spoofing the correct response is only a matter of guessing the source port.

Proof of concept

I could have reported the vulnerability at this point, but I wanted to make sure it was exploitable. A “theoretical” vulnerability just isn’t the same. POC||GTFO!

 

Let’s try to verify example.com. Creating a spoofed DNS response payload was easy: take a real response, captured by tcpdump, and manually change the domain name. nping can be used to send this response, spoofing the source IP and port:

 

nping --udp -g 53 -p 30000-39999 -S 199.43.133.53 -c 100 --rate 100000 -N -H --data 000085000001000100000000076578616d706c650000100001c00c00100001000000010038376465746563746966792d766572696669636174696f6e3d6530363663623430643165353234323362613661646539393562613433636663 scanner.detectify.com

 

The above command tries to send the fake DNS response, purporting to originate from 199.43.133.53 (the real nameserver for example.com), to scanner.detectify.com as fast as possible, cycling the source port between 30000 and 39999. Now it’s a simple matter of running that on my laptop while furiously clicking Verify over and over on Detectify’s website, right? Almost.

IP spoofing for pleasure and profit

Virtually all ISPs and datacenters today do egress filtering to prevent spoofed packets from leaving their network – and with good reason! Their most common use is DDOS attacks, especially DNS amplification attacks. I needed a host that doesn’t do such filtering. Additionally, the latency between the attacking host and the victim had to be as low as possible to maximise the chances of the fake response being received before the real one.

 

Finding such a host is left as an exercise for the reader, but I can say that I’m now the proud owner of 6 new virtual servers, 5 of them completely useless. (Luckily they were cheap.) After more furious clicking on Detectify’s site I was finally greeted with this:

 

Example.com verified
Success!

Detectify fixed the issue within 3 hours of it being reported.


 

About the author:
Evgeny Morozov is a software developer with a keen interest in security and privacy.