(Or How the Smallest Detail Can Make a Difference)
This is a guest post from Antonios Atlasis.
As it is well known to the IPv6 enthusiasts, one of the most significant changes that IPv6 brings with it, apart from supporting a really huge address space, is the improved support for Extensions and Options, which is achieved by the usage of IPv6 Extension headers. According to RFC 2460, “changes in the way IP header options are encoded allows for more efficient forwarding, less stringent limits on the length of options, and greater flexibility for introducing new options in the future.” So, by adding IPv6 Extension headers, according to the designers of the protocol, flexibility and efficiency in the IP layer is improved.
This can definitely be the case, but apart from it, it has already been shown that by abusing IPv6 Extension headers several security issues may arise (see for example my presentations at Black Hat Abu Dhabi 2012 and at the IPv6 Security Summit @ Troopers 13). This is why Enno Rey by talking straight to the point at the latest IPv6 Security Summit @ Troopers 14 described the IPv6 Extension headers as a “mess”!
Unfortunately, it seems that we have not exhausted yet all the potential security problems introduced by IPv6 Extension headers. In this article, I am going to describe a novel way of abusing IPv6 Extension Headers which can be used to evade successfully high-end IDPS commercial devices. Specifically, during the “Researching IPv6 Security Capabilities” (RISC) project organised by ERNW and in which I had the pleasure to participate, we found out that using this technique, we can evade the Tipping Point IDPS (for a full presentation of the results of the 1st phase of RISC which were presented at the IPv6 Security Summit @ Troopers 14, please check here). But, before describing how it works, let’s build our case first.
As it is explained in RFC 2460, “in IPv6, optional internet-layer information is encoded in separate headers that may be placed between the IPv6 header and the upper- layer header in a packet. There are a small number of such extension headers, each identified by a distinct Next Header value.” According to the protocol specification, “an IPv6 packet may carry zero, one, or more extension headers, each identified by the Next Header field of the preceding header.”
Let’s assume that the initial IPv6 datagram that needs to be fragmented contains the IPv6 main header (obviously), a few IPv6 Extension headers and the layer-4 header (e.g. TCP) plus its payload. Some of the IPv6 Extension headers (like the Hop-by-Hop and the Routing IPv6 Extension headers) may need to be processed by intermediate nodes, while some other (e.g. Destination Options IPv6 Extension header) may not. A part of this initial IPv6 datagram will remain unfragmented, and the rest of it will be fragmented as following:
The Unfragmentable Part will consist of the IPv6 main header plus any IPv6 Extension headers that must be processed by intermediate nodes en route to the destination (Hop-by-Hop and the Routing IPv6 Extension headers in our example).
The Fragmentable Part will consist of the rest of the packet, that is, any IPv6 Extension headers that need be processed only by the final destination node(s), plus the upper-layer header and data (that is, the Destination Options IPv6 Extension header, the TCP header and its payload in our example).
But let’s focus on Next Header values of the IPv6 Fragment Extension Headers. Regarding fragmentation, according to RFC 2460, page 20, each fragment packet (among else) is composed of an IPv6 Fragment Extension header containing “the Next Header value that identifies the first header of the Fragmentable Part of the original packet”. So, the Next Header values of the IPv6 Fragment Extension headers of ALL fragments should be the same and equal to the header value of the first header (IPv6 Extension header or layer-4) of the fragmentable part. To clarify it farther, RFC 2460 at page 21 suggests that the Unfragmentable Part of the reassembled packet consists of of all headers up to, but not including, the Fragment header of the first fragment packet (that is, the packet whose Fragment Offset is zero), with the following (among else) change: “The Next Header field of the last header of the Unfragmentable Part is obtained from the Next Header field of the first fragment’s Fragment header.” And, if there is a doubt, to clarify the situation, RFC 2460 at page 22 recommends that “The following conditions are not expected to occur, but are not considered errors if they do: … <snipped for brevity>… 2) The Next Header values in the Fragment headers of different fragments of the same original packet may differ. Only the value from the Offset zero fragment packet is used for reassembly. ”.
I suppose that the situation now is crystal clear. No matter what the Next Header values of the IPv6 Fragment Extension headers used in the fragments are, it is only the Next Header value of the IPv6 Fragment Extension header whose offset is zero (0) to be used as the Next Header value of the last header of the unfragmentable part. Yet another potential ambiguity introduced by our beloved IPv6 RFCs. But protocol ambiguities always ring the same bell: “IDPS Evasion”.
Let’s see an example: Let’s assume that the original packet that needs to be fragmented is the following:
Note: Of course, you can change, add or even remove one of the used IPv6 Extension headers, if you wish. Now, let’s assume that the fragmentable part is the following:
According to what have been described so far by RFC 2460, the aforementioned packet should be fragmented as following:
and the 2nd fragment:
Please, note the Next Header values of the IPv6 Fragment Extension headers, as recommended by RFC 2460.
Now, what if the Next Header value of the second fragment points to the layer-4 header, that is, what if the second fragment is like the following:
In this case, the IPv6 Fragment Extension header of the second fragment “points to” the layer-4 protocol, which is TCP in our example, the header value of which is 6. As described above, according to the RFC 2460 such a case should not occur but is not considered as an error if it does 🙂
Well, by testing such packets at the RISC lab together with the ERNW guys, we found out that:
1. Most of the popular Operating Systems (Windows, Linux, OpenBSD) accept such fragmented datagrams, as they actually should, according to RFC 2460.
2. Tipping Point IDPS (TOS Tipping Point, Package 18.104.22.16836 and vaccine 22.214.171.12430 digital) misinterprets such fragments and lets them pass through even if you have explicitly defined not to do so (again, more details on the tests that we run, the used configuration, etc. can be found here).
3. The above combination results in a layer-3 evasion of the Tipping Point IDPS device, which means that you can actually launch any kind of attack (from port scanning to SQLi) while remaining undetected.
Here, we should note that:
1. Tipping Point IDPS is not the only IDPS device that it has been found out to be vulnerable to the aforementioned attack, or a variation of it.
2. The specific vendor reacted rapidly and has already patched the described vulnerability (please, check their web site for available patches).
Is this the end? Well, I am afraid not 😉 IPv6 Extension Headers are a mess, indeed. More will follow, so, stay tuned!