📄 00000008.htm
字号:
<HTML><HEAD> <TITLE>BBS水木清华站∶精华区</TITLE></HEAD><BODY><CENTER><H1>BBS水木清华站∶精华区</H1></CENTER>发信人: lenx (冷·枫), 信区: Linux <BR>标 题: [安全]搞死NT/95又有新方法啦 <BR>发信站: BBS 水木清华站 (Fri Nov 14 19:57:20 1997) <BR> <BR>不过也能搞死linux :( <BR>不过, linux的patch已经有啦 :) <BR> <BR>Subject: <BR> Linux IP fragment overlap bug <BR> Date: <BR> Thu, 13 Nov 1997 22:06:15 -0800 <BR> <BR> Helu. <BR> <BR> I wrote this post a while back when the bug was first discovered. It <BR>seems as though this bug (and patch) has gotten out, so here it is, in it's <BR>entirety. <BR> <BR> As it happens, Linux has a serious bug in it's IP fragmentation module. <BR>More specifically, in the fragmentation reassembly code. More specifically, <BR>the bug manifests itself in the `ip_glue()` function.... <BR> <BR> When Linux reassembles IP fragments to form the original IP datagram, it <BR>runs in a loop, copying the payload from all the queued fragments into a newly <BR>allocated buffer (which would then normally be passed to the IP layer proper). <BR>><I>From ip_fragment.c@376: </I><BR> <BR> fp = qp->fragments; <BR> while(fp != NULL) <BR> { <BR> if(count+fp->len > skb->len) <BR> { <BR> error_to_big; <BR> } <BR> memcpy((ptr + fp->offset), fp->ptr, fp->len); <BR> count += fp->len; <BR> fp = fp->next; <BR> } <BR> <BR> While it does check to see if the fragment length is too large, which would <BR>have the kernel copy too much data, it doesn't check to see if the fragment <BR>length is too small, which would have the kernel copy WAY too data (such is the <BR>case if fp->len is < 0). <BR> <BR> To see when this happens, we need to look at how Linux adds IP datagrams <BR>to the reassembly queue. From ip_fragment.c@502: <BR> <BR> /* <BR> * Determine the position of this fragment. <BR> */ <BR> <BR> end = offset + ntohs(iph->tot_len) - ihl; <BR> <BR> Ok. That's nice. Now we have to look at what happens when we have <BR>overlaping fragments... From ip_fragment.c@531: <BR> <BR> /* <BR> * We found where to put this one. <BR> * Check for overlap with preceding fragment, and, if needed, <BR> * align things so that any overlaps are eliminated. <BR> */ <BR> if (prev != NULL && offset < prev->end) <BR> { <BR> i = prev->end - offset; <BR> offset += i; /* ptr into datagram */ <BR> ptr += i; /* ptr into fragment data */ <BR> } <BR> <BR> If we find that the current fragment's offset is inside the end of a <BR>previous fragment (overlap), we need to (try) align it correctly. Well, this <BR>is fine and good, unless the payload of the current fragment happens to NOT <BR>contain enough data to cover the realigning. In that case, `offset` will end <BR>up being larger then `end`. These two values are passed to `ip_frag_create()` <BR>where the length of the fragment data is computed. From ip_fragment.c@97: <BR> <BR> /* Fill in the structure. */ <BR> fp->offset = offset; <BR> fp->end = end; <BR> fp->len = end - offset; <BR> <BR> This results in fp->len being negative and the memcpy() at the top will end <BR>up trying to copy entirely too much data, resulting in a reboot or a halt, <BR>depending on how much physical memory you've got. <BR> <BR> We can trigger this normally unlikely event by simply sending 2 specially <BR>fragmented IP datagrams. The first is the 0 offset fragment with a payload of <BR>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -