As defined in RFC 2675 [Borman, Deering, Hinden, 1999], “a "jumbogram" is an IPv6 packet containing a payload longer than 65,535 octets”. An IPv6 datagram, due to the length of the IPv6 main header (16 bits), can support up to 65535 octets of IPv6 payload [Deering, Hinden, 1998]; this includes any IPv6 extension headers that may follow the IPv6 main header, but not the main header itself. For applications that need datagrams bigger than this (by the way, are you aware of any of this kind?), IPv6 jumbograms come into place. However, as also explained in RFC 2675, “jumbograms are relevant only to IPv6 nodes that may be attached to links with a link MTU greater than 65,575 octets” (65,535 octets of an IPv6 payload plus 40 octets for the IPv6 main header itself).
IPv6 jumbograms are defined as an IPv6 hop-by-hop option, called the “Jumbo Payload” option, that carries a 32-bit length field in order to allow transmission of IPv6 packets with payloads between 65,536 and 4,294,967,295 octets in length [Borman, Deering, Hinden, 1999].
The Payload Length field in the IPv6 header must be set to zero, while the Next Header value is also set to 0 (implying that a Hop-by-Hop header follows). So, an IPv6 Jumbogram would look like:
Now, the Hop-by-Hop header itself will look like:
where “Next header” is an 8-bit field whose value indicates the header that follows (e.g. if the next header is ICMPv6, it should be 58).
0 is the value of the Length field of the Hop-by-Hop header (the length of the Hop-by-Hop Options header in 8-octet units, not including the first 8 octets).
C2 (in hexadecimal) or 194 (in decimal) is the Jumbo Option Type.
4 is the Option Data Length.
Finally, the Jumbo Payload Length is an 32-bit unsigned integer which indicates the length of the IPv6 packet in octets, excluding the IPv6 main header but including the Hop-by-Hop Options header and any other extension headers present. The Jumbo Payload Length must be greater than 65535 (since, otherwise, there is no need to use a Jumbogram).
According to RFC 2675, the Jumbo Payload option must not be used in a packet that carries a Fragment header.
The following vulnerabilities have been discovered related with the implementation of IPv6 Jumbograms.
CVE-2007-4567: The ipv6_hop_jumbo function in net/ipv6/exthdrs.c in the Linux kernel before 2.6.22 does not properly validate the hop-by-hop IPv6 extended header, which allows remote attackers to cause a denial of service (NULL pointer dereference and kernel panic) via a crafted IPv6 packet.
CVE-2008-0352: The Linux kernel 2.6.20 through 126.96.36.199 allows remote attackers to cause a denial of service (panic) via a certain IPv6 packet, possibly involving the Jumbo Payload hop-by-hop option (jumbogram).
CVE-2010-0006: The ipv6_hop_jumbo function in net/ipv6/exthdrs.c in the Linux kernel before 188.8.131.52, when network namespaces are enabled, allows remote attackers to cause a denial of service (NULL pointer dereference) via an invalid IPv6 jumbogram, a related issue to CVE-2007-4567.
Of course, the big problem with IPv6 Jumbograms (from a tester's / researcher's perspective) is the fact that it is not that easy to find a link with an MTU suitable for supporting them. So, I was thinking about alternative approaches. One such approach could be to … fragment an IPv6 Jumbograms; I know, this does not make sense in real life (why fragment something whose intended purpose is to avoid the necessity of fragmentation) and secondly, it is “forbidden” by the corresponding RFC (but, who cares about this)? So, I decided to give it a try.
Now, the first approach would be to put the Fragment Extension header after the Hop-by-Hop header (which carries the “Jumbo” payload). In this case, there is a problem with the Payload Length field of the IPv6 main header. Typically, this should be zero for IPv6 Jumbograms, but given that we use fragment(ation), a correct Payload Length should be used to determine the end of the fragment. Nevertheless, this scenario can be tested as follows:
For 65536 bytes of IPv6 datagram (excluding the IPv6 main header), we need:
- 8 bytes for the Hop-by-Hop header
- 8 bytes for the ICMPv6 Echo Request header
- 65536 - 8 – 8 = 65520 bytes of layer 4 payload, that is 8190 octets of bytes.
Let's fragment it in 56 fragments. Assuming that our target listens to the IPv6 address 2001:db8:1:1::2 m we can use the following Chiron command:
./chiron_scanner.py vboxnet0 -sn -d 2001:db8:1:1::2 -l4_data `python -c 'print "AABBCCDD"*8190'` -luE 0'(options=Jumbo;jumboplen=65536)' -nf 56 -plength 0
It should be noted that the reassembled packet is recognised properly as an IPv6 jumbogram, and specifically, as an ICMPv6 Echo Request of 65528 bytes (65526 bytes are reached after adding the length of the Hop-by-Hop header).
The other approach is to Fragment the Hob-by-Hop header (that is, to put the Hop-by-Hop header in the fragmentable part of the initial IPv6 datagram). Of course, RFC 2460 forbids this (“ The Hop-by-Hop Options header, when present, must immediately follow the IPv6 header”), but you never know. Let's try to find out what happens in the real world, using the following Chiron command.
./chiron_scanner.py vboxnet0 -sn -d 2001:db8:1:1::2 -lfE 0 -l4_data `python -c 'print "AABBCCDD" *1'` -nf 2
The above command adds a Hop-by-Hop header in the fragmentable part of the IPv6 datagram and then, it fragments it to two fragments (for explanation of the switches, please check my previous blog post).
The tested OS were (once more):
Windows 10 Home, Version 1511, OS Build 10586.36, x64
Centos 7, kernel 3.10.0-327.3.1 x86_64
Fedora 23, kernel 4.2.8-300 x86_64
FreeBSD 10.2-RELEASE-p7, amd64
OpenBSD 5.8, GENERIC#1170 amd64
After executing it, I found out that most of the tested OS respond with an ' ICMPv6 Parameter problem, unrecognized Next Header type encountered' packet, while OpenBSD responds with an Echo Reply (OK, not a vulnerability on its own, but such an RFC noncompliance is still a bit disappointing for an OS which emphasises, among else, on standardization, correctness, and proactive security.
How can we reproduce it? Using the previous approach, but by moving the Hop-by-Hop header to the fragmentable part of the IPv6 datagram. This time the Chiron command will like:
./chiron_scanner.py vboxnet0 -sn -d 2001:db8:1:1::2 -l4_data `python -c 'print "AABBCCDD"*8190'` -luE 0'(options=Jumbo;jumboplen=65536)' -nf 56 -plength
Again, Wireshark recognises the reassembled IPv6 Jumbogram ICMPv6 Echo Request properly!
Happy Jumbo-testing :-)
Borman D., Deering S. & Hinden R. (1999). IETF RFC 2675 “IPv6 Jumbograms”, August 1999.
Deering S. & Hinden R. (1998). IETF RFC 2460 “Internet Protocol, Version 6 (IPv6) Specification”, December 1998.