Detecting C2 Over DNS

In response to the Wekby APT article written by PaloAlto, located here, I wanted to write a short post on detecting potential C2 communication over DNS and make some points regarding common misconceptions people have regarding DNS security. Many organizations today still allow DNS traffic directly out their firewalls from endpoints within the organizations network. This is a no no. Endpoint machines should only be allowed to communicate over port 53 to an internal DNS server that has been properly hardened and preferably running Linux. If this is not in place then least privilege should dictate that DNS traffic should only be allowed out of the network to organizational approved DNS servers such as OpenDNS or google DNS. Regardless of the policy within the organization, this article will help anyone trying to identify potential malicious behavior. Even if you do block outgoing DNS requests directly from endpoints to an outside service, this DNS “tunneling” method is still able to work.

Rule #1: Log DNS queries! If you run your own DNS server this is easy. Every DNS request sent to your server should be logged. If you use and pay for OpenDNS Umbrella, they provide you with methods to export logs and even a plugin for Splunk to help you centrally collect this information. If you use a service like google’s DNS or free OpenDNS, then I recommend using Bro to log your DNS traffic using network taps or mirror ports.


The first method of DNS tunneling is to have the victim machine use the attacker’s machine as a DNS server and send lookup queries to it. These queries contain base64 or base32 encoded data within them. On the other end, the attacker stitches together these queries to form the exfiltrated data. An example query is shown below.

As you can see the base64 encoded string is taking the place as the sub-domain for Sending several of these queries could form an entire file. It is important to note that blocking port 53 to the outside world and preventing endpoints from using other DNS servers will not prevent this. It will only make it somewhat harder and noisier.

To circumvent this all the attacker would have to do is make his server the authoritative nameserver for his domain. This means that if an organization forces users to use their own internal nameserver, the queries sent to that server will then be sent to the attackers nameserver for resolution. Comparison of the two techniques below.

First Method: Victim → Attacker
Second Method: Victim → Internal Nameserver — -> Attacker

Detecting C2 activities

So how do we find this stuff? As you can see these requests do not look normal in the slightest. Once DNS logs are centrally collected we can comb through them and search through our queries based on entropy, or randomness. For this I am using Splunk with the URL Toolbox app installed. This allows me to carve out queries from the DNS requests and identify the sub-domains of each. With this information I then filter based on entropy. Below is the Splunk search I created. I will send a domain query to my internal nameserver using the domain in the example above.

sourcetype=queries* NOT (dns_query=”*” OR dns_query=”*”) | ut_parse(dns_query)|ut_shannon(ut_subdomain) | where ut_shannon > 3.4 | stats count by dns_query ut_shannon

The dns_query field represents every DNS query sent to the nameserver and is then put into ut_parse and put through ut_shannon, which is then told to look at the entropy of the subdomain, represented by ut_subdomain. The magic sort of just works with this and I would recommend people read through the URL Toolbox documentation. I also told Splunk to only show me anything with an entropy level of 3.4 and above. This is just an example and should be set to whatever works with the organization in question. I also removed google and since they popped-up as false positives.

Ryan St. Germain

Ryan St. Germain