DNS patches against Kaminsky's attack are still vulnerable

Kris Kaspersky,
Endeavor Security, Inc.

The latest security patches designed to prevent DNS spoofing, don’t work. Effective attacks against DNS are still possible. This document summarizes the DNS name server attack and the client's resolver (the stub),as related to: BIND9, PowerDNS, DJBDNS, MS XP/Server 2003/Server 2008.

Brief

Dan Kaminsky (The Director of Penetration Testing for IOActive) makes himself known by discovering well-known (and well-forgotten) DNS attacks. He has refused to reveal any technical information until the Black-Hat 2008 conference and has forced DNS vendors to invest in improved protection. Yet even though the ISP’s have done everything as instructed, the problem became worse. Kris Kaspersky has analyzed the patches and discovered that they're almost useless and do not fix the real attack vector.

In short the patched systems perform two things:

  1. They randomize the transaction ID (TXID) and the source port number (SP#) as best as they can. Unfortunately, they can't! Most systems use extremely weak and predictable pseudo-random algorithms;

  2. They change the DNS cache behavior. Some systems just turn the cache off, which causes negative side-effects, including performance degradation and weakened protection. This results because the more outgoing DNS requests, the greater chance the system gets a faked DNS reply;

Port randomization doesn't solve the problem (see "port exhausting" attack scenario)and TXID is still quite predictable. In general, a dozen faked DNS replies are enough to hack the victim. Cache behavior changing reduces the impact of the DNS poisoning, but doesn't prevent DNS spoofing. To protect systems against DNS attacks we have to know how they work. For additional background on this subject, read the two following articles which covers the basics:

http://adm.freelsd.net/ADMADMID.txt
http://beezari.livejournalcom/141796.html
;

Affected systems

  • DNS servers accepting recursive queries and working over UDP without autorotation (note: some papers claim that DNS servers accepting recursive queries only from subscribers are not affected, which isn't true, since an attacker can force the subscriber to send recursive request to the DNS. for example, an attacker can send the subscriber HTML-mail with external picture links, to resolve them the victim will send the recursive query);

  • DNS client's resolver (the stub) working over UDP and accepting replies from anywhere

Non-affected systems

  • DNS servers not accepting recursive queries;

  • DNS servers and stubs working over TCP or using DNSSEC;

  • Stubs accepting DNS replies only from an internal network from its own DNS.

Conclusion

Most of DNS servers accept recursive queries – this is how they work! If DNS didnt accept recursive queries it would resolve only those names that it's aware of, such as its own domains. For example, if we have a corporative network arcme.com and a DNS server,it resolves names likemail.arcme.com, http://www.arcme.com/, http://ftp.arcme.com/, but it knows nothing about names like www.google.com. So,it has to return an error or send a query to another DNS server. It might be the ISP's DNS or the root, since the client's resolvers don't support recursive queries and rely on the DNS server. The DNS server can’t return an error if it can't resolve the name by itself, this is what DNS server need for. If stubs supported recursive queries, they wouldn’t need DNS servers.


DNS servers and stubs which use DNS over TCP aren't vulnerable, they are ‘DNS spoofing free.’ The same applies to DNSSEC, however, almost all systems use DNS over UDP which is what makes them vulnerable. Why use UDP? Is TCP less effective or too slow? No. It's the best solution for a small ISP and office networks. However, large ISP’s processing > 1,000 recursive queries per second have no choice. Under a heavy load, TCP isn't fast enough. As for DNSSEC, it's slow,but even if it was fast it wouldn't solve the problem. What's the problem? Suppose, I own the nezumi.org.ru domain name and have DNS for subdomains like
http://www.nezumi.org.ru/, souriz.nezumi.org.ru, etc. and my DNS doesn't support DNSSEC. How are you supposed to resolve souriz.nezumi.org.ru in this case? Use TCP! It's reliable and almost all DNS servers support TCP, while not every server supports DNSSEC. So, we're focusing only on servers and stubs using DNS over UDP. Within that category, we discussing: BIND9, PowerDNS, DJBDNS and MS XP/Server 2003/Server 2008 (other DNS have the same problem, so there is no reason to include them in the list).

Internal and external attacks

If an attacker is inside a local network, it's very easy to intercept DNS-queries and send faked replies to be accepted by the victim. DNS over TCP is vulnerable and doesn't prevent internal DNS spoofing. So,we're talking _only_ about external attacks. This doesn't mean that internal attacks arent a problem! It is a problem... a real problem (especially for a large local network), but what can we do? There is no ‘ready-to-use’ solution, so we have to live with it. With vulnerable servers and stubs there is less concern because local attackers are not as dangerous as the external attacks that we're discussing.

How it works

DNS attacks are different but they all have at least two phases. The first phase is to send a faked DNS reply which looks like the real one. The second phase is to perform a desired action by placing certain information into the faked reply, such as redirecting the victim to the hacker's site or DNS cache poisoning. The point is that there is no way to poison the DNS cache, if you skip the first phase of the attack and the first phase is the most complicated phase. The second is trivial.

The first phase of the attack is system and target specific. Attacks against DNS servers and stubs are very different, so we will discuss them separately.

Attacks against DNS server (Phase I)

In this scenario, we have a DNS server working over UDP and accepting recursive queries from everybody (the last condition is preferred, but isn't a sticky request for attacks since, as was mention above, an attacker can force DNS subscribers to send any request). The server accepts faked reply if TXID and SP# 16-bits fields are correct, and rejects the packet
otherwise.


An attacker sends queries to the server and gets replies, observing the TXID and SP#. Suppose the victim uses constant source port (53 by default) and a predictable TXID (for example, a simple incrementing TXID). If so, an attacker just sends a recursive query to resolve the name which is missing in the DNS cache. To achieve that, the attacker can oust the name by sending a lot of recursive queries – the cache isn't endless, so it purges all previous data.


The victim sees that the requested name is missing from the cache and sends a query to the top DNS server (the ISP's DNS or the root DNS servers). The attacker immediately sends a faked reply with the correct TXID/SP#. Or to be more exact, the attacker sends a lot of packets with different TXID (SP#), hoping that one of them will be accepted.

To prevent attacks, the latest patches randomize TXID and SP#. So theoretically, the attacker has to send (2^16 * 2^16)/2 = 2^31 = 2,147,483,648 packets on average and leaves the real DNS behind. Since, after the victim gets a reply, it doesn't listen anymore. The 2,147,483,648 packets are too many, even the attacker slows down the real DNS somehow to get extra time to send more faked packets.


Conclusion: there is no way to attack a patched DNS server by stupid brute-force. However, an attacker can determine if the victim is patched or not and if it's not, can just hack it. But why will an use stupid brute force? We will discuss below how to hack patched systems.

Attack against a stub (Phase I)

A stub doesn't accept any queries. Instead, it sends queries to its own DNS. An attacker has no way of knowing the TXID and SP#. The attacker is in the dark, so a "blind" attack is the only way to hack the victim. It's harder than a DNS server attack but still possible. First and foremost: a stub doesn't accept unexpected replies which were requested. So, an attack has to force the victim to send a certain query at a certain time. How can an attacker can do this? Simple. Just send HTML-email with pictures of external links, with one of them referring to the hacker's web-site.


Most of the mail clients automatically download pictures. Since, an attacker controls the WEB-server, the point at which the victim opens the mail is known. That is the time to send faked DNS replies. But... how? An attacker has no idea about the TXID/SP#? Unfortunately, that's wrong and we'll show why later, after describing the Phase II.

Attack against DNS server (Phase II)

An attacker asks the server to resolve name souriz.nezumi.jp which is missing from the cache, so the server sends a query to the top level server: "souriz.nezumi.jp. IN A". An attacker immediately returns a fake reply. There are two kinds of replies:


Answer: (no response)

Authority section: nezumi.jp. 2700 ; IN NS ns.nezumi.jp.

Additional section: ns.nezumi.jp. IN; A 6.6.6.6


What does it mean? An attacker says to the victim that Name Server (NS) for nezumi.jp is ns.nezumi.jp which is true but, the IP address of ns.nezumi.jp (see the additional section) is faked, this is the hacker's ns-server and the victim memorizes it and sends all following requests to *.nezumi.jp to 6.6.6.6 instead of the real ns-server (ns.nezumi.jp).

This won’t work if the victim doesn't appreciate the additional section (most DNS servers do appreciate it), or if the victim uses ‘forward confirmed reverse DNS’ to validate the given IP. If so, an attacker becomes a honest person and sends the following response:

Answer: (no response)


Authority section: nezumi.jp. 2700 ; IN NS ns.hacker.tw.


Additional section: ns.hacker.tw. IN; A 6.6.6.6


What's the difference? An attacker claims that ns.hacker.tw is the ns for nezumi.jp (this is lie, but who would know?) and gives the true IP of ns.hacker.tw (where ns.hacker.tw is the hacker's server). As a result, an attacker gets all queries for *.nezumi.jp and this is a serious flaw. The victim is unable to recognize the hacker's lie. It's possible to validate the result by asking root servers, but it takes too long and isn't acceptable for a large ISP. Yes, nezumi.jp is different from ns.hacker.tw, but it's normal. A lot of people don't own DNS and use free DNS as NS for their domains.

Attacks against a stub (Phase II)

A stub doesn't support recursive queries so, it doesn't appreciate NS. It's supposed to get an IP address for an asked name so that an attacker can't hack the whole domain. However, it's able to send a faked IP for any name. For example, a stub wonders what IP has update.company.com and an attacker convinces the victim that update.company.com has 6.6.6.6 IP. The victim caches it for a while and downloads hacked updates. Or an attacker can redirect mail/web traffic to intercept confidential information.

Attacks against patched systems

Since the second phase is really trivial, we focus on the first one. How can an attacker predict randomized TXID and SP#? There are at least two possible scenarios: a) port exhausting; b) TXID/SP# predicting.

Port exhausting

If the Source port is randomized, there is no way to predict it? Not so. Even the absolute strong random function is useless against a port exhausting attack. An attacker simply consumes as many UDP ports as possible, reducing the free pool to zero and making the next chosen port very predictable.

MS Windows for example, uses very limited port ranges (49152-65535 by default) and it's easy to consume almost all free ports, especially if the victim has other services based on UDP. MS made two serious mistakes. First, it randomized _all_ ports on network level, redesign _TdiOpenAddress@20 function of TCPIP.SYS driver, instead of changing DNSAPI.DLL to randomize the port, before passed to bind function. What's the difference? DNSAPI.DLL can't re-use ports however, some UNIX DNS servers use one of 1024 randomly chosen ports. Perhaps 1024 is too small and leads to DoS? Yes, it leads to DoS. DNS doesn't re-use ports (1024 simultaneous requests and the server is unable to accept one more request) but in fact, there is no DoS! A well-designed server uses 1024 ports, chosen from a wide range (like 1024 - 65535) and re-uses already used ports. So, port consuming does nothing and servers of this kind aren't vulnerable (however, in this case we get only 10 bits for SP# [2^10 = 1024]). MS Windows is vulnerable, especially taking into account that it has a lot of UDP services installed by default. This affects the MS DNS server, as workstation (the stub).

BIND 9, PowerDNS and DJBDNS randomize the source port on the application level, so they (theoretically) can reuse the same ports. However, even if they did this, there is no way to prevent port excusing attacks, if there is another UDP-based service allowing an attacker to consume all ports.

Predictable TXID

The success of a port exhausting attack means that we have only 16-bit randomized TXID. Suppose TXID is randomized optimally and it's absolutely unpredictable. This means that an attacker has to send 2^16/2 = 32,768 faked packets on average. That’s too much for a DNS server, but not for a workstation. Why? An IDS can detect a faked packet storm for a simple reason, the amount of DNS servers is very limited. How many workstations are on the Net? For example, take a small local network with two hundreds hosts (it's a really small network). If an attacker sends faked packets to all machines, every machine gets only a hundred packets before one of them accepts a faked packet. To bypass an IDS, an attacker can use a Bot-net or IP spoofing. However, if you take a large network with 65k hosts, even if TXID is absolutely unpredictable, one faked packet by the host is enough to hack in. (Btw, there is no reason for a storm. If an attacker isn't in a hurry, one faked packet per couple seconds/minutes works great. Especially, if an attacker has no certain target and just sends faked packets to different networks. So there is no way to detect the storm with an IDS, because there would be no storm!).


But, TXID is predictable. In fact, it's very predictable, especially if we're talking about attacks against DNS servers. An attacker sends queries and gets replies, observing the TXID. An attacker knows the pseudo-random algorithm (if the victim isn't running open-source, an attacker can reverse the code). Knowing the algorithm and having a lot of previous TXID, it's possible to predict the next TXID, especially if the pseudo-random function is weak. Numerous DNS developers have tried to improve it by reinitializing the pseudo-random function every time it's used. Yet, this is leads to a more predicable TXID, especially if system clock works as ‘a seed.’

Brief analysis shows that BIND 9 and DJBDNS generate a very predicable TXID and by rough estimates can be hacked by sending a dozen faked packets. MS DNS and PowerDNS are stronger, but vulnerable. MS Windows uses CryptGenRandom() or rand() if CryptGenRandom() fails (see Dns_GetRandomXid function) and there are some ways to force CryptGenRandom() to return an error remotely and make the system generate TXID with rand(), which is extremely predictable. Of course, this applies only for DNS server attacks, not for workstation (an attacker can't receive stub's replies – stubs don't reply).

Afterwards

This paper is a brief introduction to the problem to get the reader thinking.More information will follow on the blog site http://www.endeavorsecurity.blogspot.com/ Upcoming articles will describe MS XP/Server 2003/Server 2008, BIND 9, BJBDNS and PowerDNS, each separately and in greater technical detail.

Closing note: How to detect DNS attacks via signatures

The idea is that a normal DNS server doesn't reply twice, because it's (almost) never asked twice. A resolver sends a query and caches the reply. So, if we have a lot of DNS packets with the same content ("A" record), but different TXID/SP# – this is definitely a DNS spoofing attempt. We don't need the only request in the threshold, our IDS has to be able analyze more than one packet simultaneously or just store information about the previous packets somewhere.

Another approach could be that the IDS intercepts all outgoing DNS queries and memorizes the TXID/SP# and if it detects incoming replies which were not requested, then this is definitely a DNS spoofing attempt.

IDS installed on the host net with moderate load (small ISP, offices server) can validate the IP and NS sending a query to the root DNS servers.



No comments: