Actionable Security Intelligence
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.
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:
a) 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;
b)
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/ADM/ADMID.txt and http://beezari.livejournal.com/141796.html;
q
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 is
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);
q
DNS
client's resolver (the stub) working over UDP and accepting replies from
anywhere
q
DNS
servers not accepting recursive queries;
q
DNS
servers and stubs working over TCP or using DNSSEC;
q
Stubs
accepting DNS replies only from an internal network from its own DNS.
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 like mail.arcme.com, www.arcme.com, 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 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).
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.
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.
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^16 = 65,536 packets
on average and leaves the real DNS behind. Since, after the victim gets a reply,
it doesn't listen anymore. The 65,536
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.
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.
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.
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.
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.
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.
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).
This paper is a brief introduction to the
problem to get the reader thinking. More information will follow on the blog
site www.endeavorsecurity.com/blog.
Upcoming articles will describe MS XP/Server 2003/Server 2008,
BIND 9, BJBDNS and PowerDNS, each separately and in
greater technical detail.
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.