The Domain Name Service (DNS) allows machines to convert human readable domain names like google.com into their machine addresses.
In this post, I talk about how DNS tunneling works and present some content that I put together to aid analysts in detecting DNS tunneling in their environment.
An attacker can abuse DNS to send data between infected machines in the network and their Command and Control (C2) server. The process begins when the attacker is authoratative for a domain. Let's say they own badguys.com. In order to send data from the infected machine they simply encode the data into the subdomains. For example their hello message could be: hello.badguys.com. Of course sending OS-WinXP-User-Steve-Perm-Admin.badguys.com is going to raise suspicion as well as being an inefficient method of sending data. So, attackers may convert to hex or base32 encode data. Then the subdomain looks something like: MV4GC3LQNRSSAYTFMFRW63TT.badguys.com.
To identify this type of DNS tunnel, the analyst looks for a large number of random looking subdomains for the root domain when the C2 is actively communicating. When the infected machine is simply beaconing, the analyst expects a single (or few) subdomains requested frequently from the same infected machine.
To aid the analyst in detecting DNS tunneling, this content looks at the length of the query name field and computes it entropy. Most DNS names shouldn't be very long, and shouldn't be very random. Entropy is a mathematical way for us to express 'randomness'. A value of 8 would be perfectly random for this scenario.
We use a parser to extract the alias.host length and entropy, and then compute the average in a NWDB report. The parser requires the addition of the following lines to the index-concentrator-custom.xml and index-decoder-custom.xml files as appropriate for the environment:
<key description="Hostname Length" format="UInt32" level="IndexValues" name="alias.host.len" valueMax="1000000" defaultAction="Auto"/>
<key description="Hostname Entropy" format="Float32" level="IndexValues" name="alias.host.ent" valueMax="1000000" defaultAction="Auto"/>
<key description="Root Domain" format="Text" level="IndexValues" name="alias.host.root" valueMax="100000" defaultAction="Auto"/>
1. Security tools- security tools like AV will often use DNS tunneling to submit hashes to their servers and get additional data. This leads to a large number of randomly looking subdomains and can be filtered with the whitelist provided as part of the report. This is technically an example of DNS tunneling, it is just tunneling by the good guys.
2. DNS Servers- DNS servers make it look like a lot of queries are coming from a single host, but you cannot be sure that in the case since they are effectively proxying the queries. We cannot whitelist those servers, and simply have to pivot to logs if something seems interesting.
3. Confusing calculations- let's pretend that the attacker sent a request for google.com to check network connectivity and beacon.badguys.com in the same session. The parser will calculate a separate entropy and length for each alias.host. However, when the report runs, it loses that context and calculates the same average entropy for both based on that session. This means our averages will not be quite accurate. In a large environment though (think law of large numbers), there ought to be enough queries for google.com as part of other sessions to mitigate this issue. Using DNS logs instead of packet data fixes this issue.
4. The parser adds additional meta based on populating alias.host regardless if the protocol is DNS or not. This allows it to run against logs. It also allows me to use some of that data in HTTP reports in the future.
I request feedback on the rules and parser especially in environments with DNS logs.