DNS AAAA Record Attacks

by J. Edward Durrett

Detecting DNS Command and Control / Linux / FreeBSD

I recently read an article discusing the use of AAAA records as a way of command
and control over a remote machine.[1] It is an excellent article, and I recommend
reading it. To quickly summarize, it is possible to craft AAAA records on a DNS
server which contain commands. When I client asks for the records, those commands
can be decoded on the client and executed and the output is sent back to the name
server. This can be used to extract whole files or slowly, and covertly, execute
commands to take more control of the system and network.

The intriguing part of this method is that it is so difficult to detect[1]. Machines
are making DNS queries all the time and the traffic created by taking one file a
day isn't that much. Just opening a popular news web page sends over 100 DNS
queries and taking one /etc/passwd file is about 400 queries. That is not going to
stand out, even on a small network, if it is only done once a day. In addition, on
a mail server, multiple DNS queries are made on every message. A lightly loaded
mail server with 5,000 mails a day with rbl and url checking, will send out tens of
thousands of DNS queries in one day. This means that network analysis would be difficult.

The target machine must run the script[1], so this isn't a panic story about anyone
can control your computer with DNS queries. However, there are many ways to get the
script on the target and run at an interval, think php reverse shell, a disgruntled
employee, a spy, the guy setting next to you on an international flight who took
advantage of the few minutes you left your seat and forgot to lock your laptop,
etc. How it gets there is beyond the scope of this article, as I am looking for
detection.

In order to see the effect on some machines and on the network, I put together a
command and control script, DNSCC, that works to control both Linux and FreeBSD
targets. It is available on github:

https://github.com/durrettj/dnscc

Directions for setup are in the README file, so I am not going to repeat them here.
Once set up on the target and the command control server, running it is rather
simple:


Welcome to DNSCC!
The following commands are available:
1. Send command to target
2. Get file from target
3. Read output from target
4. Read output from target and pipe to more
5. Change type of host - Current host is type: BSD
6. Exit
Enter the number:
1
Enter command
uname -a
1. Send command to target
2. Get file from target
3. Read output from target
4. Read output from target and pipe to more
5. Change type of host - Current host is type: BSD
6. Exit
Enter the number:
3
FreeBSD lovelace 10.3-RELEASE-p4 FreeBSD 10.3-RELEASE-p4 #0: Sat May 28 09:52:35
UTC 2016 root@amd64-builder.daemonology.net:/usr/obj/usr/src/sys/GENERIC i386
1. Send command to target
2. Get file from target
3. Read output from target
4. Read output from target and pipe to more
5. Change type of host - Current host is type: BSD
6. Exit
Enter the number:


As simple as that, I am running commands on a remote machine with out being logged
in or creating and major noise.

How to Detect

On the sever side, this is easy to very difficult depending on the role. A web
server for example should not be sending out many DNS queries, and the ones it does
send out (for APIs, etc) can be narrowed down and white listed. But on a network as
a whole, it becomes tougher.

The first thing, is that nothing should be asking name servers on the internet
directly so we can log all DNS queries. A slight modification of the command in
read.sh can decode the hex in the DNS log files and then parsed for strings like
'/etc/passwd.' But, that is problematic, as the script could be modified the put
spaces between each character like ' / e / t / c / p a s s w d.' In addition, an
attacker could also wrap the output in openssl before converting it to hex, so
decoding hex and searching for strings is harder to do.

The next thought I had is to look at the log and parse get stats on how many
queries are coming from each host:
 
sed -e 's/#.*//g' query.log|sort -n| uniq -c
10232 client 10.3.1.3
22861 client 10.3.1.41

!0.3.1.41 is the target, so we do see higher queries. But, I have been command and
controlling it all day. So, I rotated the log and started again. I asked for the
output for uname -a and checked the number of queries:

sed -e 's/#.*//g' query.log|sort -n| uniq -c
19 client 10.3.1.3
15 client 10.3.1.41

As you can see, after just a few minutes, my target has made less DNS queries than
the other machine on my test network. So, this method of detection is inadequate.

sed -e 's/.*query: //g' query.log|sed -e 's/ IN.*//g'|cut -f2- -d'.'| sort -n|uniq
-c |sort -n
...
8 THE_BAD_DNS.local
...
40 msn.com
121 google.com

As you can see, The bad queries are just a blip in the logs (I cut out many, many
lines between 8 queries and 40). And this is just a few minutes on a test network,
just imagine how little this shows up on a network even a small office network.

So, I turned to the target to see what I could find out there. It is running system
accounting, and that actually shows me some rather unusual activity. The target is
running FreeBSD, and the Linux commands are slightly different, but it is the same
concept (eg drill vs. dig).

lastcomm | grep drill | sed -e 's/pts.*//g' | uniq -c
982 drill - jed

Wow, that jed user sure is having fun with the drill command. Now I have gotten to
a point where I can look into it more. So I looked at the times of the commands,
and what that user was doing at that time, 15:51:
 
lastcomm | grep 15:51 | sed -e 's/pts.*//g' | sort -n |uniq -c
1 awk - jed
1 cut - jed
7 drill - jed
1 sed - jed
1 sh - jed
2 sh -F jed
1 sort - jed
1 tr - jed
1 uname - jed
2 xxd - jed

This is what it looks like with just the uname command I sent. Fetching the
/etc/passwd file produces this:
 
lastcomm | grep 13:32 | sed -e 's/pts.*//g' | sort -n |uniq -c
1 awk - jed
1 cut - jed
441 drill - jed
1 ls - jed
1 sed - jed
1 sh - jed
2 sh -F jed
1 sort - jed
1 tcsh -F jed
1 tr - jed
2 xxd - jed

From this, I can see a pattern for detection. If drill is greater than 5 and awk,
cut and xxd are all called in the same minute, there is a compromise. With that it
is possible to write a rule for an IDS like OSSEC to file an alert. And by
narrowing town the time of these few packets leaving the network, I can inspect the
DNS logs and attempt to decode even obfuscated hex.

On production Web or Mail servers, drill (or dig) is never called during normal
operation. They are useful tools, though, and I can image cases where they might
be used to trouble shoot DNS issues, but in production that should be rare.
Furthermore, that a regular user in an Accounting or Marketing department should
not be using drill and dig and with appropriate policy in place, that can be
monitored.

System accounting exists on the major flavors of *NIX (Mac OS X, Linux, BSD,
Solaris, etc) and can be used to detect AAAA record attacks. I don't see an easy
way to detect/block this activity on the network (using snort, rate limiting DNS,
etc[1]) in general. However, limiting or eliminating outside DNS access for routers,
printers, and other devices isn't a bad idea.






References:

[1] https://isc.sans.edu/diary.html?storyid=21301
[2] https://github.com/DShield-ISC/IPv6DNSExfil








Copyright (c) 2019, Jason Edward Durrett - All content on this site, unless otherwise noted, is subject to this license.

Please contact me if any errors, such as erroneous / misleading content or missing / incomplete attribution, are found.