Bugtraq mailing list archives
A New Fragmentation Attack
From: aleph1 () DFW NET (Aleph One)
Date: Thu, 10 Jul 1997 05:45:54 -0500
http://www.dataprotect.com/ntfrag/ A New Fragmentation Attack by Thomas Lopatic, 970709 This page is brought to you by Data Protect. The attack presented in this article is not quite up to date since it applies only to Windows NT 4.0 systems which haven't applied Service Pack 3. However, it presents a quite interesting scenario which once more demonstrates that packet filtering firewalls may be insecure in very subtle ways. 1 Impact The attack affects Windows NT 4.0 hosts (up to and including Service Pack 2) that are protected by a firewall which is based on packet screening. Stateful inspection firewalls may also be concerned, depending on their implementation. Using this weakness, an outsider is able to pass IP datagrams through the firewall to the Windows NT host, i.e. access the host as if the firewall did not exist. This problem has been fixed with Service Pack 3. Upgrade NOW! 2 Description When reassembling a fragmented IP packet, the Microsoft implementation does not require the first fragment to have an offset value of zero. It merely checks, whether the sum of the lengths of the collected fragments equals the total length of the original unfragmented IP packet. If enough fragments have been received so that this condition holds, the NT stack will happily reassemble what it has got so far. So - how does it know about the total length of the original packet? Since, during normal operation, all fragments but the last have the MF (more fragments) bit set, Microsoft's stack waits until it has received a fragment F without the MF bit and then reasons that the length of the unfragmented datagram must have been offset of F + length of F. Apparently Microsoft have tried to be particularly efficient since this method is faster than traversing the whole list of fragments to check for completeness. Let me illustrate this mechanism with an example. Say that we have an original packet of 48 bytes which we send as three fragments F1, F2 and F3, each with a length of 16 bytes. Now suppose that they arrive out of order, first F2, then F3 and eventually F1. The following table shows NT's notion of the total packet length after each fragment has arrived. Fragment #Offset Length MF bit Total Length Data Collected F2 16 16 1 0 (no change, since MF 16 = 1) F3 32 16 0 48 (= offset + length =32 32 + 16) F1 0 16 1 48 (no change, since MF48 = 1) After Total Length equals Data Collected, the IP stack decides that it has received all fragments and starts reassembling. To exploit this goodie courtesy of Microsoft, we will clear the MF bit on another fragment. Suppose we send another two fragments F1, and F2 as follows. Fragment #Offset Length MF bit Total Length Data Collected F1 16 16 0 32 16 (= offset + length = 16 + 16) F2 32 16 1 32 (MF = 1, no 32 change) We have just sent two fragments, none of which has an offset of zero, yet the NT protocol stack will correctly reassemble them into a 32 byte IP packet. 3 Exploit Details Exploiting this feature is a bit more complicated than it seems at first sight. Since the IP stack stores the IP header of a fragment (to use it later for the reassembled packet) if and only if its offset is zero, we must send a decoy packet first, which must be carefully crafted so that it will be stored at exactly the same memory location as our next packet, which is the malicious one without the zero-offset-fragment. So, the bogus datagram will reuse the header information of our first datagram. Imagine that we would like to attack a WWW server behind a firewall. Then we would send one decoy to port 80, a malicious packet to 23, another decoy to port 80, another bogus packet to port 23, etc. In this way we can establish a telnet session through the packet screen. But what do we do when we hit a packet screen (e.g. screend) which requires for each fragmented packet a fragment with an offset of zero to be present? We send such a fragment and simply give it a time to live that is short enough so that it will reach the firewall but never the destination host. Another option would be to insert an invalid checksum into its IP header so that it will be dropped at the destination host. 4 Example Code In order to back up the above theory with an example, I have written a short program which sends a decoy UDP datagram to port 9 (discard) of my NT system and after that another UDP datagram to port 7 (echo). I have used port 255 as the source port. The program runs on NetBSD 1.2 and should be easily portable to any BSD system featuring the Berkeley Packet Filter. Here is the output of tcpdump after an example run. bob:/usr/home/tl# tcpdump tcpdump: listening on ed0 01:54:38.751853 bob.255 > alice.discard: udp 248 (frag 256:256@0+) 01:54:38.752252 bob > alice: (frag 256:256@256) 01:54:38.752645 bob > alice: (frag 512:256@256) 01:54:38.753054 bob > alice: (frag 512:256@512+) 01:54:38.755716 alice.echo > bob.255: udp 248 01:54:38.755992 bob > alice: icmp: bob udp port 255 unreachable ^C 6 packets received by filter 0 packets dropped by kernel bob:/usr/home/tl# As can be easily seen, alice, my NT system, responds (line seven in the above paragraph) to the two fragments sent by bob (lines five and six in the above paragraph). The first two fragments (lines three and four) make up the decoy packet. Eventually, alice gets an ICMP message, since bob does not have any service listening at port 255. The source code for this little demo program is available. 5 Conclusions Once again it has been shown that packet filtering firewalls can be a dangerous thing to deploy. In a way, they always have to rely on the protected hosts to handle IP packets in the expected manner. And sometimes these hosts fail to do so. Hopefully this example will show people that a solid application gateway may be a better choice than all those fast and flexible packet screens. 6 Service Pack 3 This Service Pack fixes the problem mentioned above. It introduces a check, whether the IP stack has seen a fragment with an offset of zero, before reassembly is done. However, I will not stop investigating. Maybe Microsoft has hidden some more goodies for us to discover. :)
Current thread:
- CERT Advisory CA-97.21 - SGI Buffer Overflow Vulnerabilities, (continued)
- CERT Advisory CA-97.21 - SGI Buffer Overflow Vulnerabilities Aleph One (Jul 17)
- slight misinformation in CA-97.21 Dave Kormann (Jul 17)
- msg00234.html brush () SEARCH POL PL (Jul 17)
- CERT Vendor-Initiated Bulletin VB-97.05 - Vul in Lynx Temporary Aleph One (Jul 16)
- Sun Security Bulletin #00146 Aleph One (Jul 16)
- Sun CDE 1.0.1: login bug Isaac (Jul 28)
- Re: Sun CDE 1.0.1: login bug Doug Hughes (Jul 29)
- CERT Vendor-Initiated Bulletin VB-97.06 - Vul in Lynx Downloading Aleph One (Jul 16)
- Re: [linux-security] so-called snprintf() in db-1.85.4 (fwd) Joe Zbiciak (Jul 10)
- A New Fragmentation Attack Aleph One (Jul 10)