Hacking

DNS cache snooping

Dejan Lukan
October 9, 2012 by
Dejan Lukan

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:

Earn two pentesting certifications at once!

Earn two pentesting certifications at once!

Enroll in one boot camp to earn both your Certified Ethical Hacker (CEH) and CompTIA PenTest+ certifications — backed with an Exam Pass Guarantee.

[plain]

# 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: 173.194.35.148 muc03s01-in-f20.1e100.net

Address 2: 173.194.35.144 muc03s01-in-f16.1e100.net

Address 3: 173.194.35.147 muc03s01-in-f19.1e100.net

Address 4: 173.194.35.145 muc03s01-in-f17.1e100.net

Address 5: 173.194.35.146 muc03s01-in-f18.1e100.net

Address 6: 2a00:1450:4016:800::1010 muc03s01-in-x10.1e100.net

[/plain]

We can see that the query returned five addresses: 173.194.35.144, 173.194.35.145, 173.194.35.146, 173.194.35.147 and 173.194.35.148, which are used for load balancing.

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:

[plain]

# nslookup -norecursive <a href="http://www.rapid7.com/">www.rapid7.com</a>

[/plain]

First, we try to use nslookup command to ask the DNS server 8.8.8.8 (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:

[plain]

# nslookup -norecursive -type=A www.rapid7.com

Server:  8.8.8.8

Address: 8.8.8.8#53

Non-authoritative answer:

*** Can't find www.rapid7.com: No answer

[/plain]

Afterward, we can use the -recursive option, which should reveal the IP address as can be seen below:

[plain]

# nslookup -recursive -type=A www.rapid7.com

Server:  8.8.8.8

Address: 8.8.8.8#53

Non-authoritative answer:

Name: www.rapid7.com

Address: 208.118.227.10

[/plain]

We can see that the DNS server 8.8.8.8 recursively asked other DNS servers for the information about the hostname www.rapid7.com. At the end of the query, it returns an address 208.118.227.10, 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:

[plain]

# nslookup -norecursive -type=A www.rapid7.com

Server:  8.8.8.8

Address: 8.8.8.8#53

Non-authoritative answer:

Name: www.rapid7.com

Address: 208.118.227.10

[/plain]

Now the non-recursive query returned an IP 208.118.227.10. We saw how to figure out if a DNS server is vulnerable to DNS cache snooping.

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 8.8.8.8, which takes approximately 30.387 milliseconds (check the avg measurement of the last line of the output below):

[plain]

# ping -c 3 8.8.8.8

PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.

64 bytes from 8.8.8.8: icmp_req=1 ttl=47 time=29.7 ms

64 bytes from 8.8.8.8: icmp_req=2 ttl=47 time=30.7 ms

64 bytes from 8.8.8.8: icmp_req=3 ttl=47 time=30.6 ms

--- 8.8.8.8 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

[/plain]

Then we need to try to request some hostname using the DNS nameserver 8.8.8.8, 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 8.8.8.8, which took 31 milliseconds:

[plain]

# dig @8.8.8.8 www.google.com

; <<>> DiG 9.9.1-P2 <<>> @8.8.8.8 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       173.194.35.146

www.google.com.         256     IN      A       173.194.35.144

www.google.com.         256     IN      A       173.194.35.145

www.google.com.         256     IN      A       173.194.35.147

www.google.com.         256     IN      A       173.194.35.148

;; Query time: 31 msec

;; SERVER: 8.8.8.8#53(8.8.8.8)

;; MSG SIZE  rcvd: 123

[/plain]

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 8.8.8.8.

Let's try to resolve a hostname www.imdb.com, which as we'll see is not in a local cache:

[plain]

# dig @8.8.8.8 www.imdb.com

; <<>> DiG 9.9.1-P2 <<>> @8.8.8.8 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       207.171.162.180

;; Query time: 61 msec

;; SERVER: 8.8.8.8#53(8.8.8.8)

;; MSG SIZE  rcvd: 77

[/plain]

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:

[plain]

# dig @8.8.8.8 www.imdb.com

; <<>> DiG 9.9.1-P2 <<>> @8.8.8.8 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       72.21.203.211

;; Query time: 31 msec

;; SERVER: 8.8.8.8#53(8.8.8.8)

;; MSG SIZE  rcvd: 77

[/plain]

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:

[plain]

# nslookup -type=A www.google.com 8.8.8.8 -debug

Server:         8.8.8.8

Address:        8.8.8.8#53

------------

QUESTIONS:

www.google.com, type = A, class = IN

ANSWERS:

->  www.google.com

internet address = 173.194.35.146

ttl = 300

->  www.google.com

internet address = 173.194.35.148

ttl = 300

->  www.google.com

internet address = 173.194.35.144

ttl = 300

->  www.google.com

internet address = 173.194.35.145

ttl = 300

->  www.google.com

internet address = 173.194.35.147

ttl = 300

AUTHORITY RECORDS:

ADDITIONAL RECORDS:

------------

Non-authoritative answer:

Name:   www.google.com

Address: 173.194.35.146

Name:   www.google.com

Address: 173.194.35.148

Name:   www.google.com

Address: 173.194.35.144

Name:   www.google.com

Address: 173.194.35.145

Name:   www.google.com

Address: 173.194.35.147

[/plain]

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.

FREE role-guided training plans

FREE role-guided training plans

Get 12 cybersecurity training plans — one for each of the most common roles requested by employers.

Conclusion

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.

Dejan Lukan
Dejan Lukan

Dejan Lukan is a security researcher for InfoSec Institute and penetration tester from Slovenia. He is very interested in finding new bugs in real world software products with source code analysis, fuzzing and reverse engineering. He also has a great passion for developing his own simple scripts for security related problems and learning about new hacking techniques. He knows a great deal about programming languages, as he can write in couple of dozen of them. His passion is also Antivirus bypassing techniques, malware research and operating systems, mainly Linux, Windows and BSD. He also has his own blog available here: http://www.proteansec.com/.