cipherdyne.org

Michael Rash, Security Researcher



Metasploit DNS Cache Poisoning and iptables Countermeasures

Metasploit and DNS Cache Poisoning Attacks On July 23rd, H D Moore, I)ruid, and the Metasploit Project released an exploit for the Dan Kaminsky DNS cache poisoning attack - the full details of which will be released at the Blackhat Briefings. We know that source port prediction for recursive queries is a key component to successfully poison a nameserver's cache, and the Metasploit exploit code offers the ability to check a targeted nameserver for predictable source ports. This check is implemented by sending a set of TXT queries against the metasploit.com domain to a targeted server, and - if recursion is enabled - the server will in turn send these queries (which are randomized and therefore not cached) to a nameserver that is authoritative for the metasploit.com domain. The information returned by the metasploit.com nameserver contains the source port the targeted nameserver used to issue the queries. If the source port exhibits a high degree of predictability (such as if the query-source address * port named.conf directive is used or if an external NAT device removes randomness in the source port on its own), then it is much easier to spoof responses to queries against the target from other nameservers and increase the chances that one of these spoofed responses will be cached.

Here is an example of using the source port check feature in Metasploit. Some output has been abbreviated, and the IP addresses 11.1.1.1 (hostname: attacker) and 22.2.2.2 (hostname: target) are used only for illustration purposes: [attacker]# ./msfconsole
msf > use auxiliary/spoof/dns/bailiwicked_host
msf auxiliary(bailiwicked_host) > set RHOST 22.2.2.2
RHOST => 22.2.2.2
msf auxiliary(bailiwicked_host) > check
[*] Using the Metasploit service to verify exploitability...
[*] >> ADDRESS: 22.2.2.2 PORT: 30001
[*] >> ADDRESS: 22.2.2.2 PORT: 30001
[*] >> ADDRESS: 22.2.2.2 PORT: 30001
[*] >> ADDRESS: 22.2.2.2 PORT: 30001
[*] >> ADDRESS: 22.2.2.2 PORT: 30001
[*] >> ADDRESS: 22.2.2.2 PORT: 30001
[*] FAIL: This server uses a static source port and is vulnerable to poisoning
So, the source port used by the targeted nameserver is always 30001 - convenient.

If we examine the traffic generated by Metasploit on the wire, the TXT queries exhibit some nice structure. Note the spoofprobe-check and .red.metasploit.com strings in both the incoming queries responses (actually, incoming queries contain the bytes |03|red|0a|metasploit|03|com in Snort syntax): [attacker]# tcpdump -i eth0 -l -nn port 53
22:53:40.594082 IP 11.1.1.1.40866 > 22.2.2.2.53: 0+ TXT? spoofprobe-check-1-10913572965.red.metasploit.com. (67)
22:53:40.730809 IP 22.2.2.2.53 > 11.1.1.1.40866: 0 1/1/0 TXT "22.2.2.2:30001 IN IN::TXT spoofprobe-check-1-10913572965.red.metasploit.com" (182)
Further, in the query responses, the string IN::TXT is also returned. So, using this information, we can build iptables rules that leverage the string match extension to inspect application layer data for these strings. We can then have iptables take action such to log or drop packets that match.

If a nameserver is running locally on a Linux system, then the following rules detect inbound requests from the attacker (see the usage of the iptables --hex-string argument to describe the non-printable bytes in the incoming DNS request), as well as responses from the metasploit.com server to outbound recursive requests from the targeted nameserver. Note that you might want to combine the LOG rules with the iptables limit match in order to reduce the number of log messages created during an actual attack. Still, I find that having more data is usually good, and the number of source port reconnaissance queries is much less than the number of spoofed responses when a cache poisoning attempt is made anyway, so it shouldn't be too burdensome to leave off the limit match. [target]# iptables -I INPUT 1 -p udp --dport 53 -m string --string "spoofprobe-check" --algo bm -m string --hex-string "|03|red|0a|metasploit|03|com" --algo bm -j LOG --log-prefix "METASPLOIT DNS RECON QUERY "
[target]# iptables -I INPUT 1 -p udp --dport 53 -m string --string "spoofprobe-check" --algo bm -m string --hex-string "|03|red|0a|metasploit|03|com" --algo bm -j DROP

[target]# iptables -I INPUT 1 -p udp --sport 53 -m string --string "IN::TXT" --algo bm -m string --string "spoofprobe-check" --algo bm -m string --string ".red.metasploit.com" --algo bm -j LOG --log-prefix "METASPLOIT DNS RECON RESP "
[target]# iptables -I INPUT 1 -p udp --sport 53 -m string --string "IN::TXT" --algo bm -m string --string "spoofprobe-check" --algo bm -m string --string ".red.metasploit.com" --algo bm -j DROP
Similar rules can be added to the FORWARD chain (along with specifying the internal subnet or input interface so that directionality can be established) for nameservers that are deployed on a separate system behind a Linux system running iptables. The most important rules above are probably the first two, since matching packets reveal the source IP of the attacker. However, this is of limited use because the actual cache poisoning attack will involve packets spoofed from other authoritative nameservers, and it is possible to collect source port information from other sources. Still, having information about someone doing source port predictability reconnaissance against one of your nameservers with Metasploit is worth knowing.

With the rules above in place, the 'check' step in Metasploit is unable to tell that the targeted nameserver even responds to recursive queries at all, and back on the firewall system several METASPLOIT DNS RECON QUERY log messages are written to syslog by iptables: msf auxiliary(bailiwicked_host) > check
[*] Using the Metasploit service to verify exploitability...
[*] ERROR: This server is not replying to recursive requests

[target]# tail /var/log/messages
Aug 2 06:39:55 target kernel: [933142.545502] METASPLOIT DNS RECON QUERY IN=eth0 OUT= MAC=00:13:46:3b:41:4c:00:12:46:c2:60:44:09:00 SRC=11.1.1.1 DST=22.2.2.2 LEN=96 TOS=0x00 PREC=0x00 TTL=63 ID=33573 DF PROTO=UDP SPT=40273 DPT=53 LEN=76
Aug 2 06:39:55 target kernel: [933142.637446] METASPLOIT DNS RECON QUERY IN=eth0 OUT= MAC=00:13:46:3b:41:4c:00:12:46:c2:60:44:09:00 SRC=11.1.1.1 DST=22.2.2.2 LEN=96 TOS=0x00 PREC=0x00 TTL=63 ID=33574 DF PROTO=UDP SPT=40273 DPT=53 LEN=76
On another note, before using Metasploit to test your DNS infrastructure to see if it is exploitable, it is important to know whether your local network allows spoofed packets out. Many firewalls can be configured to drop spoofed packets from internal systems, and even my little LinkSys router does this. Because there is no mechanism in Metasploit currently (as far as I know) to detect whether your local network filters spoofed packets (and building such a mechanism would be tricky for various technical reasons), an incorrect assumption can result in a cache poisoning attack that has no possibility of succeeding but that also generates thousands of DNS queries at the same time.

Finally, for those unpatched nameservers running behind an iptables firewall, the SNAT --random option can provide a work-around for predictable source ports. Nevertheless, the emphasis should always be on patching vulnerable servers since the source port problem is only one aspect of the vulnerability in DNS.