DNS Abuse



Introduction.

Lately on bugtraq there have been a number of DNS abuse related posts. DNS is the protocol that translates numerical IPs to Fully Qualified Domain Names (FQDN) and vice versa.
I won't explain the protocol, you can always look up the DNS related RFCs:
1031, 1032, 1033, 1034, 1035

Basic Concepts.

A DNS server (Name server - NS) resolves IPs to names and vice versa. How does this resolution work? Let's see an example:

Our NS is ns.hispahack.org and the name we have been requested to resolve is "memo.lala.lelo.com".
Our name server strips the address. First, it checks with one of the Internet ROOT-name servers who is in charge of the "com" domain. Our NS has a ROOT-NS list with their associated IPs, in order to not resolve their IPs (if this was the case, our NS wouldn't be able to resolve anything). So it checks for the "com" domain. From this it obtains the NS for the "com" domain. Then, it asks this NS who serves the "lelo" domain. It obtains another NS address, asks it who serves the "lala" domain, obtains another NS address and asks it what is the "memo" machine IP. We have just obtained the IP for "memo.lala.lelo.com", let's say it is 123.123.123.123.

Here finishes our NS job, after resolving the address it stores it in its cache for future queries. The cache is a register that stores the last resolved addresses, in case someone else makes a query for the same address.

Note: We have just described how a NS that supports recursion works (most of them). This means that if the name server doesn't serve the address he is asked to resolve, it will forward the query to another NS in order to resolve it, till it gets either the resolution or an irresolvable address error. If the NS does not support recursion, then if it serves the domain for the address we request to resolve it will resolve it, if not it will tell us that it can't resolve that IP and ask us to resolve it for ourselves.

So... the vulnerabilities described below

ARE ONLY EFFECTIVE WITH RECURSIVE DNS SERVERS

DNS Datagrams.

The DNS protocol communicates using UDP, an unconnected transport protocol, that is, it throws a datagram to the network and forgets about it. That makes impossible to have flow control, error correction, etc. This is an important point, as UDP can not, opposite to TCP, keep a flow control between two hosts, with the well known sequence numbers.

So, if we want to spoof or drop into a UDP connexion we don't need to predict the sequence numbers.
You can check the DNS datagrams structure in RFC 1035, if you need more details about it.

Given the transport protocol does not identify the datagrams by connexion, the DNS protocol needs to assign each datagram an "identification" in order to tell what datagram belongs to a query, etc.
This identification is called QueryID and is assigned by the the source NS (the one that queries). From this moment all this resolution related datagrams will be identified with the same QueryID.

Fake data injection into a NS cache.

We are getting to the interesting part, how to cheat a NS in order to resolve a name to the IP we want it to or vice versa.

Method A: NS Impersonation.

For this attack, we will need:

- A primary DNS

This is the technique...

Let's say we are m1.hh.org (1.1.1.1) and the NS we control is ns.xs.com, and we want to spoof ns.victim.com as XXX.lechuck.org

We are trying to impersonate the lechuck.org NS and make ns.victim.com believe that it resolved correctly XXX.lechuck.org. In order to create this fake information datagram, the victim.com NS has to ask us about it, and then we will answer. But as we are not the lechuck.org NS we can't know what the ns.victim.com QueryID will be. Thus, we have a problem, how do we guess what QueryID the XXX.lechuck.org query datagram will have?

If we query ns.victim.com for an address ns.xs.com serves (e.g. www.xs.com), ns.victim.com will contact ns.xs.com and will ask it the www.xs.com address, our name server will answer and it will be done. Given we previously sniffed the connexion with our name server from ns.victim.com asking for www address, we would know what was the QueryID it used.
DNS protocol QueryID is not a random or pseudo random generated number as with some TCP implementations seqnums, it is sequential, this is, after each query it adds one to the QueryID. It is this way because QueryID wasn't designed to prevent spoofs, but to allow the server to tell what answer belongs to a query and vice versa.

So, after we obtain the victim NS QueryID, we create a DNS datagram with the fake information we want to transmit (XXX.lechuck.org <-> 1.1.1.1), as if lechuck.org NS sent it, and targeted at ns.victim.com.
We send a query to ns.victim.com asking him for some address of the lechuck.org domain and then we send him the spoofed answer datagram.
Instead of sending just a datagram it is wise to send some datagrams, with consecutive QueryIDs, because between we obtained the QueryID and we query for lechuck.org the victim NS could have received other queries, and the QueryID could have increased slightly.

So, if ns.victim.com receives our answer before the lechuck.org NS answer (if it exists) or before the error saying that domain doesn't exist (if it doesn't exist) we will have in the victim NS cache the fake information we wanted to inject.

Method B: Data injection in the answer.

For this attack we will need a primary NS as in the other method.

This technique consists in...

When a NS queries another NS it doesn't know how many answers it can receive to its query, and it doesn't care, as it will accept all the information.
So, if when querying a NS, besides (or instead of) the information it asks for, it receives our fake information, the source NS will accept it and we will have that information in the source DNS cache :)

Applied to the above case, we just need to prepare our NS (ns.xs.com) to reply with the fake information (XXX.lechuck.org <-> 1.1.1.1) to a NS queries (ns.victim.com) and make the victim NS ask our NS.

This is an easier and more effective method, though it requires more resources in order to work, as we have to modify our name server program or program code that works as such and replies with our fake information.

Impact.

Besides the use all of you are thinking for this DNS attacks (IRC fooling) there's a lot of more serious attacks, that could compromise a lot of systems:

- NFS (Network File Sharing) in systems that export based on host names

- r* services (rlogin, rsh, etc.) impersonating trusted hosts.

- TCP Wrappers that rely in the host name in order to perform the access checks.

- ...

Conclusion.

The DNS protocol is vulnerable to these attacks, and probably much more vulnerabilities.

The first attack can be avoided if the transport protocol was something like TCP, with "random" sequence numbers, or by using more or less random QueryIDs.

The second vulnerability is inherent to the DNS protocol, and will need of a rewrite of the DNS specification in order to control that we receive the answers to what we have just asked.

References.

For those that wish to learn more of this, take a look at:

- "Addressing weaknesses in the Domain Name System protocol"  PostScript  PDF

- RFC 1536
 

APPENDIX : Putting method B into practice

Let's suppose we have everything we need, a domain primary NS host and another host where we want to run the fake DNS information injector.

Suppose we have the following:

- Primary name server: ns.xs.com
- Host where we run the injector: 123.123.123.123

I'm going to show what will be the required changes to a DNS server configuration files, assuming it is "named" (bind), the one you will find in most un*x servers.

First, let's check in the named configuration file where the domains it serves information is stored. This file is /etc/named.boot (though last bind versions have moved it to /etc/named.conf and have changed slightly the file structure, in which case you must adapt my explanations). In our example, it contains the following:


directory /var/named

cache              .                            root.cache
primary           xs.com                  db.xs.com
secondary       robin.org               db.robin.org


Let's check it line by line: directory /var/named : Base directory where the domain configuration files are stored.
primary xs.com db.xs.com : It is a primary NS for he xs.com domain, and uses the file in the db.xs.com file (This is the important one) secondary robin.org : It is a secondary NS for the robin.org domain and uses the file db.robin.org (This one is not important for us)

So, we have to take a look at the file db.xs.com (that as we know will be in /var/named):


xs.com.                        IN        SOA     ns.xs.com. root.xs.com. (
                                                            1997062100
                                                            28800
                                                            7200
                                                            604800
                                                            86400)

xs.com.                        IN         NS      ns.xs.com.

localhost                       IN        A        127.0.0.1
XXX                                 IN        A        10.0.0.1
elaine.xs.com.                IN        A        10.0.0.2


the first lines refer to the domain configuration, who manages it, expiration dates, etc.

Then we find the domain name servers configuration:

xs.com.                         IN      NS      ns.xs.com.

This line specifies that "ns.xs.com" serves the xs.com domain.

Here is where we are to modify the file. We will insert a line that creates a subdomain and puts the injector host as name server of this subdomain. To the right of an IN NS there can only be a FQDN, that is, we can't put in there a numerical IP. Thus, we need to create a host and then assign an IP to it. The first modification will be this as we supposed before:

xs.com.                         IN      NS      ns.xs.com.
sub.xs.com.                         IN      NS      ns1.xs.com.

Now we have to assign an IP to this new host we created (ns1.xs.com). In order to assign a numerical IP to a FQDN, we use the "IN A" RR, as you can see in the following lines:

XXX                                   IN      A       10.0.0.1
elaine.xs.com.                  IN      A       10.0.0.2

The second line assigns the IP 10.0.0.2 to the FQDN elaine.xs.com. The trailing dot of elaine.xs.com. is important, because if we don't put a dot in there (as with XXX) named adds at the end of it the domain (xs.com).

So, in order to insert the line we want, and as we have supposed before, we will use:

ns1.xs.com.                     IN      A       123.123.123.123

That's it, we have the name server set up for the spoof. We just have to reload the information into named (killall -HUP named), wait for the information to propagate and run our injector program.

You can use  jizz (C source) as the injector program.


This article was aimed at giving you some knowledge on DNS and the well known DNS Spoofing methods, hope you've enjoyed it :)

Finally, I wish to thank Els Apostols for the information referring to the second method I've explained, which was unknown to me, and their vulnerable NS test web page.

Cheers,
XXX
 

(C) 1997-2001 by !Hispahack
Para ver el web en las mejores condiciones, usa una resolución de 800x600 y Netscape Navigator