[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:
- 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.
- 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.
- 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 www.rapid7.com
[/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.
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.