Wednesday, July 9, 2008

DNS Poisoning

With Dan Kaminsky's latest vulnerability, I wanted to shed some light on the subject.

First if you don't know the basics of DNS Poisoning, check out this link.

Important Facts to Understand For DNS
  • DNS almost always uses UDP in a simple request-response fashion (one packet to spoof for poisoning)
  • DNS servers ignore "incorrect" responses (wrong transaction ID), and lots of "incorrect" responses do no harm. Wrong port numbers are ignored by the tcp stack, not the actual DNS server, but again relatively no harm done with wrong port numbers (maybe some firewall logs).
How To Poison A Cache

In order to successfully poison the cache of a resolver three things must happen:
  1. You must query the resolver to trigger it to query an authoritative DNS server (this is for the record you want to posion).
  2. You must spoof the response packet from the authorative DNS server the resolver is sending it's query to
  3. Your spoof packet must arrive at the resolver before the legitimate packet arrives
Step one is quite easy, even if the resource record is cached you can keep repeating the process as the cache will eventually expire. Step three is easy as your packet will already be formed and can be sent immediately while the legitamate packet must actually be queried at the authoritative server. Step 2 is a the hard part.

How To Spoof a DNS Response Packet

There are three things that must be spoofed correctly on the response packet.
  1. The source IP address, which is the IP address of the authoritative DNS server (easy to get a hold of)
  2. The source port that the resolver used (can be relatively easy)
  3. The transaction ID the resolver used (this is suppose to be the hard part)
If you have a range of possible port numbers or transaction IDs you can send multiple spoofed packets hoping one of them matches.

One can do some reconnaissance using an authoritative DNS server they control. First, one sends queries to the resolver that cause it to query the authoritative server in their control. They will see the port number and the transaction ID used for that query. This approach will allow for more information to be gained without triggering any alarms compared to a port scan.

A number of resolvers use the same source port for all queries, some even use port 53 for the source port. Ones that don't use the same source port rely on the OS to give it a source port for each query and in most cases this far from a random number and one can easily figure out the probable next port(s).

Finally comes the transaction ID. This is more random then the source port, but exactly how random has been debated for quite some time. Check out "DNS Cache Poisoning - The Next Generation" by Joe Stewart (PDF). If you know the pattern of this "randomness", your guessing can be greatly refined and have a much higher success rate. Patches have been put out over the years to fix this specific issue, but apparently it still isn't fixed or isn't secure enough.

Kaminsky's Vulnerability

While the exact vulnerability hasn't been released by Kaminsky, we can be pretty sure he has figured out a better way to guess the transaction ID. Or come up with a range that is feasible for spoofing.

While I won't speculate what the approach is (as requested by Kaminsky), I do feel he will show that the 16bit field for the transaction ID is not nearly big enough even if you use a truly random number. Therefore the patch will make it so the source port is random which would another ~16bits of randomness. Note: It is approximately 16bits as there are ranges of ports the OS would most likely not allocate.


This is a great reason to turn on DNSSec. Even if we get another 16 bits of randomness we have only pushed out the underlinging problem for another time. DNSSec will allow for responses to be authenticated using todays current standard for encryption.