BBS水木清华站∶精华区

发信人: lenx (冷·枫), 信区: Linux 
标  题: [安全]搞死NT/95又有新方法啦  
发信站: BBS 水木清华站 (Fri Nov 14 19:57:20 1997) 
 
不过也能搞死linux  :( 
不过, linux的patch已经有啦 :) 
 
Subject:  
              Linux IP fragment overlap bug 
     Date:  
              Thu, 13 Nov 1997 22:06:15 -0800 
 
    Helu. 
 
    I wrote this post a while back when the bug was first discovered.  It 
seems as though this bug (and patch) has gotten out, so here it is, in it's 
entirety. 
 
    As it happens, Linux has a serious bug in it's IP fragmentation module. 
More specifically, in the fragmentation reassembly code.  More specifically, 
the bug manifests itself in the `ip_glue()` function.... 
 
    When Linux reassembles IP fragments to form the original IP datagram, it 
runs in a loop, copying the payload from all the queued fragments into a newly 
allocated buffer (which would then normally be passed to the IP layer proper). 
From ip_fragment.c@376: 
 
        fp = qp->fragments; 
        while(fp != NULL) 
        { 
                if(count+fp->len > skb->len) 
                { 
                    error_to_big; 
                } 
                memcpy((ptr + fp->offset), fp->ptr, fp->len); 
                count += fp->len; 
                fp = fp->next; 
        } 
 
    While it does check to see if the fragment length is too large, which would 
have the kernel copy too much data, it doesn't check to see if the fragment 
length is too small, which would have the kernel copy WAY too data (such is the 
case if fp->len is < 0). 
 
    To see when this happens, we need to look at how Linux adds IP datagrams 
to the reassembly queue.  From ip_fragment.c@502: 
 
        /* 
         *      Determine the position of this fragment. 
         */ 
 
        end = offset + ntohs(iph->tot_len) - ihl; 
 
    Ok.  That's nice.  Now we have to look at what happens when we have 
overlaping fragments...  From ip_fragment.c@531: 
 
        /* 
         *      We found where to put this one. 
         *      Check for overlap with preceding fragment, and, if needed, 
         *      align things so that any overlaps are eliminated. 
         */ 
        if (prev != NULL && offset < prev->end) 
        { 
                i = prev->end - offset; 
                offset += i;    /* ptr into datagram */ 
                ptr += i;       /* ptr into fragment data */ 
        } 
 
    If we find that the current fragment's offset is inside the end of a 
previous fragment (overlap), we need to (try) align it correctly.  Well, this 
is fine and good, unless the payload of the current fragment happens to NOT 
contain enough data to cover the realigning.  In that case, `offset` will end 
up being larger then `end`.  These two values are passed to `ip_frag_create()` 
where the length of the fragment data is computed.  From ip_fragment.c@97: 
 
        /* Fill in the structure. */ 
        fp->offset = offset; 
        fp->end = end; 
        fp->len = end - offset; 
 
    This results in fp->len being negative and the memcpy() at the top will end 
up trying to copy entirely too much data, resulting in a reboot or a halt, 
depending on how much physical memory you've got. 
 
    We can trigger this normally unlikely event by simply sending 2 specially 
fragmented IP datagrams.  The first is the 0 offset fragment with a payload of 
size N, with the MF bit on (data content is irrelevant).  The second is the 
last fragment (MF == 0) with a positive offset < N and with a payload of < N. 
 
    Every linux implementation I have been able to look at seems to have this 
problem (1.x - 2.x, including the development kernels). 
 
    Oh, by the way, NT/95 appear to have the bug also.  Try sending 10 - 15 of 
these fragment combos to an NT/95 machine. 
 
    Special thanks to klepto for bringing the problem to my attention and 
writing the initial exploit. 
 
            route|daemon9           route@infonexus.com 
 
------[Begin] -- Guby Linux ------------------------------------------------- 
 
/* 
 *  Copyright (c) 1997 route|daemon9  <route@infonexus.com> 11.3.97 
 * 
 *  Linux/NT/95 Overlap frag bug exploit 
 * 
 *  Exploits the overlapping IP fragment bug present in all Linux kernels and 
 *  NT 4.0 / Windows 95 (others?) 
 * 
 *  Based off of:   flip.c by klepto 
 *  Compiles on:    Linux, *BSD* 
 * 
 *  gcc -O2 teardrop.c -o teardrop 
 *      OR 
 *  gcc -O2 teardrop.c -o teardrop -DSTRANGE_BSD_BYTE_ORDERING_THING 
 */ 
 
/* 
 * 此处删去很多字, 嘿嘿, 嘿嘿 
 */ 
 
/* EOF */ 
 
------[End] -- Guby Linux ---------------------------------------------------- 
 
    And the patch: 
 
------[Begin] -- Helu Linux ------------------------------------------------- 
 
--- ip_fragment.c       Mon Nov 10 14:58:38 1997 
+++ ip_fragment.c.patched       Mon Nov 10 19:18:52 1997 
@@ -12,6 +12,7 @@ 
  *             Alan Cox        :       Split from ip.c , see ip_input.c for history. 
  *             Alan Cox        :       Handling oversized frames 
  *             Uriel Maimon    :       Accounting errors in two fringe cases. 
+ *             route           :       IP fragment overlap bug 
  */ 
 
 #include <linux/types.h> 
@@ -578,6 +579,22 @@ 
                        frag_kfree_s(tmp, sizeof(struct ipfrag)); 
                } 
        } 

+        /* 
+         * Uh-oh.  Some one's playing some park shenanigans on us. 
+         * IP fragoverlap-linux-go-b00m bug. 
+         * route 11.3.97 
+         */ 

+        if (offset > end) 
+        { 
+                skb->sk = NULL; 
+                printk("IP: Invalid IP fragment (offset > end) found from %s\n", 
in_ntoa(iph->saddr)); 
+                kfree_skb(skb, FREE_READ); 
+                ip_statistics.IpReasmFails++; 
+                ip_free(qp); 
+                return NULL; 
+        } 
 
        /* 
         *      Insert this fragment in the chain of fragments. 
 
------[End] -- Helu Linux ---------------------------------------------------- 
 
EOF 
 
-- 
※ 修改:·lenx 於 Nov 14 19:57:55 修改本文·[FROM:  162.105.118.33] 
※ 来源:·BBS 水木清华站 bbs.net.tsinghua.edu.cn·[FROM: 162.105.118.33] 

BBS水木清华站∶精华区