RFC 1858
Security Considerations for IP Fragment Filtering
RFC 1858: Security Considerations for IP Fragment Filtering π
Okay bestie, let's get into this one. RFC 1858 is an Informational doc from the Network Working Group, dated October 1995. The authors are G. Ziemba (Alantec), D. Reed (Cybersource), and P. Traina (cisco Systems). The title block doesn't list anything it obsoletes or updates, so there's nothing to chase there π
Status of This Memo
This memo gives information to the Internet community. It does not specify an Internet standard of any kind, and it can be distributed freely with no limits πΈ
Abstract
IP fragmentation can be used to disguise TCP packets from IP filters in routers and hosts. π This document walks through two methods of attack and the remedies that stop them π₯
1. Background
So sysadmins basically rely on networking vendors to ship them packet filters. These filters keep attackers away from private systems and data, while still letting friendly traffic move between private networks and the Internet. That's why it matters so much for vendors to think ahead about possible attacks and build sturdy defenses π‘οΈβ¨
The global Internet has grown a lot, and so has the number of "undesirable elements" acting antisocially π Recently we've seen new kinds of attacks on hosts, and some of them have led to sensitive data getting compromised. Not it π
Attackers are getting sneakier too. They've started poking at the less obvious parts of the Internet Protocol. IP fragmentation is a really useful feature when you've got a bunch of different kinds of networks linked together, but it also creates several potential problems, and this doc digs into them π§
2. Filtering IP Fragments
IP packet filters on routers come with a user interface that hides fragmentation from the admin. Conceptually, the filter is applied to each IP packet as one complete entity, and honestly that's the whole illusion π¦
One approach, described by Mogul [1], is to track what the filter rules decided for the first fragment (FO==0) and then apply that same decision to the later fragments of the same packet. The filtering module keeps a list of packets indexed by source address, destination address, protocol, and IP ID. When the initial (FO==0) fragment shows up and the MF bit is set, a list item gets allocated to hold the result of the filter access checks. When packets with a non-zero FO arrive, the module looks up the list element with a matching SA/DA/PROT/ID and applies the stored result, pass or block. When a fragment with a zero MF bit shows up, the list element gets freed π
This method, or some refined version of it, could successfully remove every trace of the offending whole packet. But it has some real difficulties. Fragments that arrive out of order, maybe because they took different paths, break one of the design assumptions, and unwanted fragments can slip through as a result π¬ And if the filtering router sits on one of several parallel paths, the filtering module won't see every fragment, so it can't guarantee full fragment filtering for packets that should be dropped.
Here's the good news, though. We don't actually need to remove every fragment of a bad packet β¨ The "interesting" information lives in the headers at the start, so filters are generally applied only to the first fragment. Non-first fragments pass through without filtering, because if the first fragment is missing, the destination host can never finish reassembling the packet, so the whole thing gets thrown out anyway π
The Internet Protocol lets you split packets into pieces so tiny that they're impractical because of the data and computational overhead. Attackers can sometimes abuse normal filter behavior and these weird fragment sequences to sneak disallowed packets past the filter π In normal practice, that kind of pathological fragmentation never gets used, so it's safe to drop those fragments without breaking normal operation π
3. Tiny Fragment Attack
With a lot of IP implementations, you can force an unusually small fragment size on outgoing packets. If the fragment size is small enough to push some of a TCP packet's header fields into the second fragment, the filter rules that look for patterns in those fields won't match. And if the filtering implementation doesn't enforce a minimum fragment size, a disallowed packet can get through just because it never hit a match ππ«Ά
The doc quotes STD 5, RFC 791 here:
Every internet module must be able to forward a datagram of 68
octets without further fragmentation. This is because an internet
header may be up to 60 octets, and the minimum fragment is 8
octets.
Now, this is the important bit. For security purposes, it's not enough to just guarantee that a fragment has at least 8 octets of data past the IP header. Why? Because important transport header info, like the CODE field of the TCP header, might be sitting past the 8th data octet π
3.1 Example of the Tiny Fragment Attack
In this example, the first fragment has only eight octets of data, which is the minimum fragment size. For TCP, that's just enough to hold the source and destination port numbers, but it forces the TCP flags field into the second fragment π
Filters trying to drop connection requests (TCP datagrams with SYN=1 and ACK=0) can't test those flags in the first octet, so they'll typically ignore them in later fragments. Iconic behavior, not in a good way π
Here are the two fragments:
FRAGMENT 1
IP HEADER
+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+
| | ... | Fragment Offset = 0 | ... | |
+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+
TCP HEADER
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Source Port | Destination Port |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Sequence Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
FRAGMENT 2
IP HEADER
+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+
| | ... | Fragment Offset = 1 | ... | |
+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+
TCP HEADER
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Acknowledgment Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Data | |U|A|P|R|S|F| |
| Offset| Reserved |R|C|S|S|Y|I| Window |
| | |G|K|H|T|N|N| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3.2 Prevention of the Tiny Fragment Attack
Routers can stop this kind of attack by enforcing certain limits on the fragments coming through. Specifically, the first fragment has to be big enough to contain all the header info that's needed π§
There are two ways to make sure the first fragment of a "passed" packet has all the required fields. One is direct, and the other is indirect β¨
3.2.1 Direct Method
There's some number TMIN, which is the minimum length of a transport header needed to contain "interesting" fields, meaning fields whose values matter to packet filters. That length is measured from the start of the transport header in the original, unfragmented IP packet π
TMIN depends on the transport protocol involved, and also on the particular filters currently configured. So it's not one fixed number, it's a moving target πΈ
The direct method works by computing the length of the transport header in each zero-offset fragment and comparing it against TMIN. If the transport header length is less than TMIN, the fragment gets discarded. Non-zero-offset fragments don't need checking, because if the zero-offset fragment is discarded, the destination host can't finish reassembly. So far, we have:
if FO=0 and TRANSPORTLEN < tmin then
DROP PACKET
Here's the twist, though π The "interesting" fields of the common transport protocols, except TCP, live in the first eight octets of the transport header. So you can't push them into a non-zero-offset fragment. That means, as of this writing, only TCP packets are vulnerable to tiny-fragment attacks, and the test doesn't need to run on IP packets carrying other transport protocols. A better version of the tiny fragment test might therefore look like this:
if FO=0 and PROTOCOL=TCP and TRANSPORTLEN < tmin then
DROP PACKET
BUT, as the section on overlapping fragments below discusses, this test doesn't block every fragmentation attack. It's actually unnecessary once a more general technique is used π€π₯
3.2.2 Indirect Method
The indirect method is built on this observation: when a TCP packet gets fragmented so that "interesting" header fields get pushed out of the zero-offset fragment, there must be a fragment with FO equal to 1 somewhere in the set π¦
Now the flip side. If a packet with FO==1 shows up, it could be a sign that there's a zero-offset fragment in the fragment set with a transport header length of eight octets. Discarding this one-offset fragment will block reassembly at the receiving host, and it works just as well as the direct method above π β¨
4. Overlapping Fragment Attack β¨
4.1. Example of the Overlapping Fragment Attack π
okay so this one is giving sneaky villain arc π bestie, the fragments are big enough to pass the minimum size rules from the last section. the filter is set up to drop TCP connection request packets π ββοΈ
the first fragment has values like SYN=0 and ACK=1, so it slides right through the filter like nothing happened π
the second fragment starts at a fragment offset of eight octets and has TCP Flags that are different from the first one, like SYN=1 and ACK=0. since it's not a 0-offset fragment, the filter doesn't check it, so it gets through too π«
then the receiving host, if it fully follows the algorithms in RFC 791, puts the packet back together as a connection request because the "bad" data showed up later π main character attacker energy, no notes π¦
the whole trick is that the late data overwrites the early data during reassembly, and the filter never looked at it π
FRAGMENT 1
IP HEADER
+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+
| | ... | Fragment Offset = 0 | ... | |
+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+
TCP HEADER
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Source Port | Destination Port |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Sequence Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Acknowledgment Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Data | |U|A|P|R|S|F| |
| Offset| Reserved |R|C|S|S|Y|I| Window |
| | |G|K|H|T|N|N| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
.
.
.
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| (Other data) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
FRAGMENT 2
IP HEADER
+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+
| | ... | Fragment Offset = 1 | ... | |
+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+
TCP HEADER
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Acknowledgment Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Data | |U|A|P|R|S|F| |
| Offset| Reserved |R|C|S|S|Y|I| Window |
| | |G|K|H|T|N|N| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
.
.
.
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| (Other data) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
and if the receiving host has a reassembly algorithm that stops new data from overwriting data it already got, no problem, we just send Fragment 2 first, then Fragment 1, and it's the same successful attack π₯ the order is flexible, the vibe is not πΈ
4.2. Prevention of the Overlapping Fragment Attack π‘οΈ
bestie, here's the tea: no standard actually requires an overlap-safe reassembly algorithm, so the chance that hosts are vulnerable to this is honestly pretty big π¬
the good news is routers can block this "attack" by doing better in their IP filtering code π if the filtering module enforces a minimum fragment offset for fragments with non-zero offsets, it can stop overlaps from landing on the filter parameter parts of the transport headers β¨
for TCP, that minimum is sixteen octets, so the TCP flags field is never inside a non-zero-offset fragment π― if a TCP fragment has FO==1, it SHOULD be discarded, because it only starts eight octets into the transport header. and bonus: dropping FO==1 fragments also protects against the tiny fragment attack we talked about earlier π
RFC 791 says an IP stack MUST be able to pass an 8 byte IP data payload without further fragmentation, since fragments sit on 8 byte boundaries π¦ an IP header can be up to 60 bytes long with options, so the minimum MTU on a link SHOULD be 68 bytes.
a typical IP header is only 20 bytes, which leaves 48 bytes of data π§ nobody in the real world should EVER be generating a TCP packet with FO=1 π, because that would take a previous system chopping IP data down to the 8 byte minimum AND a 60 byte IP header. no thanks π ββοΈ
so a general algorithm for making filters work against both the tiny fragment attack and the overlapping fragment attack looks like this:
IF FO=1 and PROTOCOL=TCP then
DROP PACKET
if filtering based on fields in other transport protocol headers is provided in a router, the minimum could be greater, depending on where those fields sit in the header π
and if filtering is allowed on data past the sixteenth octet of the transport header, whether because of a flexible user interface or filters for some brand new transport protocol, dropping FO==1 packets might NOT be enough π not me being the one who has to explain that π«£
5. Security Considerations π
bestie, this whole memo is about the security side of filtering fragmented IP packets, so yeah, it's serious business π«Ά
6. Acknowledgements π
the attack scenarios here came out of chats on the firewalls mailing list back in May of 1995 π the people who helped were Darren Reed <avalon@coombs.anu.edu.au>, Tom Fitzgerald <fitz@wang.com>, and Paul Traina <pst@cisco.com> π
7. References π
[1] Mogul, J., "Simple and Flexible Datagram Access Controls for Unix-based Gateways", Digital Equipment Corporation, March 1989.
[2] Postel, J., Editor, "Internet Protocol - DARPA Internet Program Protocol Specification", STD 5, RFC 791, USC/Information Sciences Institute, September 1981.
[3] Postel, J., Editor, "Transmission Control Protocol - DARPA Internet Program Protocol Specification", STD 7, RFC 793, USC/Information Sciences Institute, September 1981.
[4] Clark, D., "IP Datagram Reassembly Algorithms", RFC 815, MIT Laboratory for Computer Science/Computer Systems and Communications Group, July 1982.
Authors' Addresses π
G. Paul Ziemba Alantec 2115 O'Nel Drive San Jose, CA 95131
EMail: paul@alantec.com
Darren Reed Cybersource 1275A Malvern Rd Melbourne, Vic 3144 Australia
EMail: darrenr@cyber.com.au
Paul Traina cisco Systems, Inc. 170 W. Tasman Dr. San Jose, CA 95028
EMail: pst@cisco.com
π¦ where this page comes from
- ietf: rfc1858 1995-10
- π girlified by claude-haiku-5-5 on : a language model's rewrite of the original, under its terms