DNS or name servers are servers that resolve a hostname to their IP representation. There are numerous DNS servers out there, all of which resolve specific domains, but each of them stores specific DNS records. Those records can be the following: A, AAAA, NS, MX, etc. All of the DNS servers are connected together to form a hierarchical DNS network. Let’s query our own local DNS server to resolve a hostname www.google.com:
# nslookup www.google.com 192.168.1.1 Server: 192.168.1.1 Address 1: 192.168.1.1 Name: www.google.com Address 1: 22.214.171.124 muc03s01-in-f20.1e100.net Address 2: 126.96.36.199 muc03s01-in-f16.1e100.net Address 3: 188.8.131.52 muc03s01-in-f19.1e100.net Address 4: 184.108.40.206 muc03s01-in-f17.1e100.net Address 5: 220.127.116.11 muc03s01-in-f18.1e100.net Address 6: 2a00:1450:4016:800::1010 muc03s01-in-x10.1e100.net
We can see that the query returned five addresses: 18.104.22.168, 22.214.171.124, 126.96.36.199, 188.8.131.52 and 184.108.40.206, which are used for load balancing.
2. DNS Queries
The primarily job of a DNS server is to respond to DNS queries. A DNS query is a question such as: “Hello DNS server, please tell me the IP of a host www.google.com”. Whenever a DNS server receives such a query, it has to look up the IP of the domain and return the corresponding IP address. A DNS server can look up the information about the hostname’s address in local cache. If the hostname-IP combination is present, it can immediately return the result. Otherwise it has to send the query forward to its DNS server, asking it for an IP of www.google.com. That DNS server does the same thing.
The purpose of a DNS server is to provide a hostname-to-IP translation for local domains that are configured in local zone files. But those are not the most common requests the DNS server will have to resolve; the most common requests are those that the DNS server has no knowledge of. When such a query is received a DNS server can execute one of the following queries:
1. Recursive Query: Since the DNS server doesn’t have any knowledge about the hostname in the query, it will ask its own DNS server to resolve it. The recursive query thus always returns the IP address of the hostname if such an IP exists. Recursive queries are not required to be supported by DNS servers.
2. Iterative Non-Recursive Query: If the DNS server doesn’t have any knowledge about the hostname in the query, it returns a list of DNS servers, which might have such information. But if the hostname-IP pair is in the local cache, the corresponding IP is returned. Non-recursive queries must be supported by all DNS servers.
3. DNS Cache Snooping: Non-Recursive Queries are Enabled
DNS cache snooping is a process of figuring out the already resolved queries by the DNS server. This can be useful if we want to check the hostnames that the local network (the one using the DNS name server) already resolved. This means that nodes on the local network using that DNS server requested specific hostnames in the near past, which can be used to snoop what web pages the users are visiting at any give time.
A DNS server is susceptible to DNS cache snooping if we can make a non-recursive query to a DNS server looking for already resolved hostnames. To check whether a DNS server is susceptible to DNS snooping we can try to find the IP address of a hostname by querying DNS server non-recursively; by not asking further DNS servers for an answer if the DNS server did not know it.
We can do that with a nslookup command:
# nslookup -norecursive <a href="http://www.rapid7.com/">www.rapid7.com</a>
First, we try to use nslookup command to ask the DNS server 220.127.116.11 (Google DNS server) to resolve the hostname www.rapid7.com non-recursively with the use of the -norecursive option. In the output below, we can see that the nslookup command doesn’t reveal the IP address of www.rapid7.com:
# nslookup -norecursive -type=A www.rapid7.com Server: 18.104.22.168 Address: 22.214.171.124#53 Non-authoritative answer: *** Can't find www.rapid7.com: No answer
Afterward, we can use the -recursive option, which should reveal the IP address as can be seen below:
# nslookup -recursive -type=A www.rapid7.com Server: 126.96.36.199 Address: 188.8.131.52#53 Non-authoritative answer: Name: www.rapid7.com Address: 184.108.40.206
We can see that the DNS server 220.127.116.11 recursively asked other DNS servers for the information about the hostname www.rapid7.com. At the end of the query, it returns an address 18.104.22.168, which is an IP address of the hostname www.rapid7.com.
Then we can again use the -norecursive option, which should now reveal the IP address. The reason for this is that when -recursive was used, the DNS server stored the returned IP address with a hostname in its cache. And then it can return the result even with non-recursive search as long as the entry exists in the cache (the result can be returned without recursively searching). We can see the output of a non-recursive query below:
# nslookup -norecursive -type=A www.rapid7.com Server: 22.214.171.124 Address: 126.96.36.199#53 Non-authoritative answer: Name: www.rapid7.com Address: 188.8.131.52
Now the non-recursive query returned an IP 184.108.40.206. We saw how to figure out if a DNS server is vulnerable to DNS cache snooping.
3. DNS Cache Snooping: Non-Recursive Queries are Disabled
To snoop a DNS server we can use non-recursive queries, where we’re asking the cache to return a given resource of any type: A, MX, CNAME, PTR, etc. We can do this by setting the recursion desired (RD flag) in query to 0. If the entry exists in the DNS cache, it will be returned. Otherwise the DNS server will reply with information about other servers that can better answer the query; in most cases we’ll receive the root.hints file back.
Usually, this can be disabled when configuring the DNS server by disabling the non-recursive queries. But even if only recursive queries are allowed, we can sometimes still detect whether a certain entry was taken from a cache or not. There are two techniques for doing that:
a. By checking the time the query takes to process. If the query time is approximately equal to the time it takes to send packets to the server, then the entry might have been already been present in the cache, since it didn’t spend any time querying other DNS servers.
We can check this by first using the ping tool to measure the RTT (round trip time) of a few ICMP packets being sent to the specific nameserver. The next example sends three ICMP packets to a DNS server 220.127.116.11, which takes approximately 30.387 milliseconds (check the avg measurement of the last line of the output below):
# ping -c 3 18.104.22.168 PING 22.214.171.124 (126.96.36.199) 56(84) bytes of data. 64 bytes from 188.8.131.52: icmp_req=1 ttl=47 time=29.7 ms 64 bytes from 184.108.40.206: icmp_req=2 ttl=47 time=30.7 ms 64 bytes from 220.127.116.11: icmp_req=3 ttl=47 time=30.6 ms --- 18.104.22.168 ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 2003ms rtt min/avg/max/mdev = 29.725/30.387/30.769/0.491 ms
Then we need to try to request some hostname using the DNS nameserver 22.214.171.124, but with a tool that also displays the time it took to execute the query. Such a tool is dig. The example below sends a DNS query for www.google.com to the DNS server 126.96.36.199, which took 31 milliseconds:
# dig @188.8.131.52 www.google.com ; <<>> DiG 9.9.1-P2 <<>> @184.108.40.206 www.google.com ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 39294 ;; flags: qr rd ra; QUERY: 1, ANSWER: 5, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 512 ;; QUESTION SECTION: ;www.google.com. IN A ;; ANSWER SECTION: www.google.com. 256 IN A 220.127.116.11 www.google.com. 256 IN A 18.104.22.168 www.google.com. 256 IN A 22.214.171.124 www.google.com. 256 IN A 126.96.36.199 www.google.com. 256 IN A 188.8.131.52 ;; Query time: 31 msec ;; SERVER: 184.108.40.206#53(220.127.116.11) ;; MSG SIZE rcvd: 123
The time taken to send an ICMP packet to the nameserver and receive a response took about 30 milliseconds, while the DNS query took 31 milliseconds. The time measurements are very close, so the entry www.google.com was probably in the cache of the DNS nameserver 18.104.22.168.
Let’s try to resolve a hostname www.imdb.com, which as we’ll see is not in a local cache:
# dig @22.214.171.124 www.imdb.com ; <<>> DiG 9.9.1-P2 <<>> @126.96.36.199 www.imdb.com ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 28806 ;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 512 ;; QUESTION SECTION: ;www.imdb.com. IN A ;; ANSWER SECTION: www.imdb.com. 9410 IN CNAME us.dd.imdb.com. us.dd.imdb.com. 33 IN A 188.8.131.52 ;; Query time: 61 msec ;; SERVER: 184.108.40.206#53(220.127.116.11) ;; MSG SIZE rcvd: 77
The time taken to complete this query was 61 milliseconds, which means that the time taken to complete the query has doubled. This is a reasonable indication that the hostname www.imdb.com was not in a local cache. If we try to request the same hostname again, we can see that the time now is only 31 milliseconds (the same as before), which is probably because of the fact that the hostname-IP pair was put in a local cache by a previous request:
# dig @18.104.22.168 www.imdb.com ; <<>> DiG 9.9.1-P2 <<>> @22.214.171.124 www.imdb.com ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 53647 ;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 512 ;; QUESTION SECTION: ;www.imdb.com. IN A ;; ANSWER SECTION: www.imdb.com. 10776 IN CNAME us.dd.imdb.com. us.dd.imdb.com. 36 IN A 126.96.36.199 ;; Query time: 31 msec ;; SERVER: 188.8.131.52#53(184.108.40.206) ;; MSG SIZE rcvd: 77
b. By checking the TTL when querying a vulnerable DNS server as opposed to another root DNS server.
Because the non-recursive queries are not allowed, the only option is to use recursive queries that will be put in the cache on the DNS nameserver. But even if that is the case, we can figure out whether the hostname was previously in the cache or not. To do that, we can check the TTL value of the response, which should be considerably low if the entry was previously stored in the cache.
We can check the TTL value by executing the command below:
# nslookup -type=A www.google.com 220.127.116.11 -debug Server: 18.104.22.168 Address: 22.214.171.124#53 ------------ QUESTIONS: www.google.com, type = A, class = IN ANSWERS: -> www.google.com internet address = 126.96.36.199 ttl = 300 -> www.google.com internet address = 188.8.131.52 ttl = 300 -> www.google.com internet address = 184.108.40.206 ttl = 300 -> www.google.com internet address = 220.127.116.11 ttl = 300 -> www.google.com internet address = 18.104.22.168 ttl = 300 AUTHORITY RECORDS: ADDITIONAL RECORDS: ------------ Non-authoritative answer: Name: www.google.com Address: 22.214.171.124 Name: www.google.com Address: 126.96.36.199 Name: www.google.com Address: 188.8.131.52 Name: www.google.com Address: 184.108.40.206 Name: www.google.com Address: 220.127.116.11
In the output above, the TTL value is 300, which is considerably low number. That probably indicates that the hostname www.google.com was already in the cache when query was made.
We’ve seen how to check whether the hostnames have recently been resolved by the specific DNS nameserver, which can be used to check out what hostnames the users of that nameserver were recently using.