Testing pfSense as an IPv6 Firewall - A Weird Case (Testing IPv6 Security Devices, Part 2)

pfSense is a clone of m0n0wall and, to the best of my knowledge, the eldest open source IPv6 firewall which is still maintained by its developers. Therefore, it should be expected that its maturity level should be good enough for normal usage.

 

The latest pfSense version currently available is 2.3.3, based on FreeBSD 10.3-RELEASE-p16.

pfSense provides the same capabilities with OPNsense regarding the IPv6 configuration of its interfaces, the deployment of DHCPv6 server, the sending of Router Advertisements and their configuration, etc. So, the only difference from an IPv6 configuration perspective between pfSense and OPNsense is the capability of filtering IPv6 Extension headers, which, nevertheless, does not seem to really work.

Testing IPv6 Filtering Capabilities of pfSense – A Weird Behaviour

Despite the lack of a filtering capability for IPv6 Extension headers, I tested pfSense as an IPv6 firewall. I will spare you most of the details, I will focus on a weird situation that I encountered.

 

First, I easily noticed (e.g. by introducing some deliberate delay between fragments of the same datagram) that pfSense performs deep packet inspection (i.e. it does not forward any fragment, until it receives them all to reassembly and examine the initial pre-fragmentation IPv6 datagram).

 

Then, during some legitimate fragmentation testing case, I noticed that I was receiving an ICMPv6 Parameter Problem / Erroneous header field encountered message (see first figure), but I did not understand why. As we can see from this figure, the packets that were sent where two fragments of a TCP (SYN) header, the first of which was 8 bytes long whilst the second (last) was 12 bytes long. This split is a completely legitimate one according to the procedure described in [RFC 2460].

 

The two fragments and the response received back are depicted at the first Wireshark output. 

To identify the reason, I had to capture and examine the traffic as received at the end host (the final “target”). This is depicted in the next Wireshark screenshot, which in my opinion explains a lot: It seems that pfSense after examining the IPv6 datagram, it refragments it in two fragments, so as to send them as they were received. However, due to a bug, presumably, the first fragment is 12 bytes long and the second, inevitably, 8 bytes long. However, as [RFC 2460] clearly explains, all but the last fragments should be multiple of octets of bytes long. Given that the offset of the fragments is also denoted in octets of bytes (e.g. offset at a Fragment Extension header equal to 1 denotes an actual offset of 8 bytes long, offset equal to 2 denotes an actual offset of 16 bytes, and so on), the aforementioned split creates inevitably fragmentation overlapping.

 

In such a case, the final recipient, if implements [RFC 5722], it will simply drop all the fragments of such a datagram and the consequences will “only” be operational ones (i.e. legitimate traffic will be dropped, without a reason). However, in case the final target accepts fragmentation overlapping, and especially if the newest fragments override the previous received, this could have some security implications. Specifically, an attacker could carefully craft a fragmented datagram so as to avoid firewall detection, but to be acceptable from the final target. This would lead to firewall evasion (in an a new post, after this issue is patched, I may explain how this could be achieved).

 

In the meantime, the mitigation would be: a) to patch all end systems so as to implement [RFC 5722] (and thankfully this is typically the case for the majority of the modern Operating Systems), and b) to do drop the fragmented packets at the perimeters. Of course, in case that you use pfSense, this could be achieved using the command line only since such an option is not available in the Web interface (in a new post I may also explain how do it).

 

A final thought: Given that pfSense is a web interface for some FreeBSD capabilities, it could be the case that the aforementioned bug is actually a FreeBSD bug of version of version 10.3 p16. Therefore, I have reported the issue to both FreeBSD and pfSense sec teams.

 

Update

As I was informed by the pfSense Security team, the aforementioned behavior appears to be caused by the scrub feature in pf. If you disable scrub, the problem behavior disappears and the fragments arrive at the destination with the expected format. To disable scrub on pfSense firewalls, visit System > Advanced, Firewall/NAT Tab, and check "Disable Firewall Scrub". Moreover, the same problem happens on a stock FreeBSD system with pf, so it should be an upstream issue in FreeBSD or pf.
FreeBSD guys are already working on this.
Stay tuned, for more info and more testing results.