A “poisoned” DNS cache contains spoofed DNS records which may be provided back to clients instead of the official, real answers. This article summarizes the initial problem, a few ways to exploit it to poison a cache, and a few remedies to help prevent cache poisoning or at least notice if the data has been compromised.
The initial DNS design in 1983 included a header field containing an ID number used to associate server replies with the original client query. A DNS query contains the question containing the name, record type, and class to lookup in addition to the unique transaction ID number. The responding server provides back the question details and the same ID number with its DNS response. DNS is most commonly used via UDP which allows spoofing of source IP addresses. Provably, a third-party, even malicious system, can race against another nameserver (using a spoofed source IP) to respond with the same ID number and details first so its provided answers can be cached and served instead. (Later responses are ignored or not seen by the resolver.)
The transaction ID is a 16-bit number which allows 65,536 different values. Some early implementations just incremented the number which allowed for somewhat guessing of ID numbers soon to be used. Other implementations did use random numbers but without a good variety. But regardless of their randomness, even a one-time match can put unintended data into the DNS cache and return it to DNS clients. Of course, snooping devices on the network can see the IDs in queries in real-time and attempt to send back a spoofed answer immediately.
Since DNS records have a cache time-to-live, DNS cache poisoning for existing cached items is limited to before the real record is cached the first time or when it expires. In addition to answers, DNS responses can also provide Authority Section NS delegations and Additional Section addresses. Depending on the DNS implementation, this information may also be cached, used to find other DNS record, or even returned back to DNS clients as answers. In the 1980’s and early 1990’s, this additional data could also provide DNS records for unrelated names. This was partially fixed in various DNS softwares by ignoring any additional data that was out of bailiwick for the query name. In other words, the query name in an answer would need to be a subdomain for any authority section and additional section names. If not, that supplementary data wouldn’t be cached.
Various DNS resolvers had different policies or algorithms on what DNS data they would trust to cache, utilize, and return to clients. Such as a successfully-validated DNSSEC answer from an authoritative server wouldn’t be superceded in the cache by a data from an additional section in a response.
The types of cache poisoning techniques vary. The standard technique is to provide back an different answer (in the answer section) only. (For example, if it is address record, the attacker could control the new target address.) A second technique is to provide back an authority section with a new or different NS delegation. A third technique is to provide an address record in the additional section. The techniques can be combined for different affects. For example, the additional section can provide an address for the NS target name provided in the authority section.
While cache poisoning techniques were known for over a decade, with various mediations, in 2008, Dan Kaminsky presented on the BlackHat-conference ideas that could increase the likelihood of poisoning a cache.
- Newer hardware and networks would allow a large amount of spoofed responses.
- Guessing the transaction ID wouldn’t require a full set of 65 thousand different attempts, but based on the Birthday Paradox, (where a set of random numbers would have some same numbers repeated) a smaller group of ID numbers could be attempted.
- Queries for unique, unknown names not in the cache would require resolvers to generate new queries.
- Various techniques can prompt for DNS lookups for these new names.
- Spoofed responses would provide a NS delegation with an address for that target name in the additional section.
- The spoofed responses would have very long time-to-lives so they stay cached and used without being replaced for a long time.
This technique could also be enhanced to use that spoofed NS delegation and additional section to point to a nameserver under control by a unknown third-party (the attacker). This would mean that the resolver would look up new names (assuming the cache didn’t already contain existing valid records) via the attacker’s own nameserver which would be cached (likely with their long TTLs) and returned to the unknowing customers.
Under the current design of standard DNS, there is no fix for the problem. But there are several ideas and techniques to help limit cache poisoning.
- Improve randomness of the transaction IDs.
- Use different randomized UDP source ports (from a large 16-bit range), so responses have to come back to the correct UDP port (CVE-2008-1447).
- Experimentally use mix-cased query names in the question and require that the answer used the same mixed-case name (such as yoUrBAnK.EXAmPlE.cOM).
- Use firewall rate limiting to slow down or stop many incoming UDP DNS responses. (Note that rate limiting on the authoritative servers could make cache poisoning easier by allowing attacker’s own responses to be seen first.)
- Encourage the world’s routers to not allow spoofed source IP addresses which shouldn’t originate from their networks.
- Provide more authoritative nameservers and resolvers shuffle through them more frequently (so attackers would have to spoof from more source IPs).
- Instead of UDP, use TCP with its handshake to prevent spoofed source addresses.
- Use DNS-over-TLS for communication via a secure TLS connection.
- Use DNSSEC so the resolver won’t accept changed responses (because a third-party won’t be able to create a signature without the private key).
Various others exist, but these are some of the common techniques.