Hacker News new | past | comments | ask | show | jobs | submit login
FreeBSD pf bypass when using IPv6 (enricobassetti.it)
72 points by todsacerdoti 8 months ago | hide | past | favorite | 52 comments



The most important thing:

> Additionally, the scrubbing process has fixed the packet, so now any operating system behind the firewall accepts the packet.

Ie if you are running a router based on pf (including pfSene and OPNSense, I suppose) you are probably fine, because you have only ssh and webgui on this host.

If you have a full OS running some services (eg MySQL and like) for which you rely on the firewall to block the external connections (instead of binding to localhost or LAn interface) then you are at risk.

Attacker should know what you are running that service or probe the known running hosts, so the opportunity is low.

ADD: it's not clear for me, but looks like this works for the forwarded (aka routed) packets as well. If yes, the 'known hosts' still apply but exposure is a bit bigger. If you are running pf firewalls with a full IPV6 connectivity - update ASAP.


Author here. I confirm that OPNSense was vulnerable. It has been fixed in v23.7.1 (August 8, 2023): https://forum.opnsense.org/index.php?topic=35298.0

We haven't tested pfSense, but I suppose that they are vulnerable too as they use `pf` and they are FreeBSD-based.


Thanks!

Can you clarify, does that works on the forwarded packets? I assume it should, given the vuln in the scrubbing function, but it would help if that would be stated clearly.


Yes, it works on forwarded packets. In the example ruleset in the blog post, `em1` and `em2` are two network interfaces (victim and attacker, think them as LAN and WAN respectively), and the FreeBSD machine is configured as router/firewall.


I haven't been able to determine if OpenBSD's `pf` is also affected. Anyone know?


Author here. No, OpenBSD's `pf` is not affected.


IIRC FreeBSD has a quite outdated version of pf, that hasn't been synced with OpenBSD upstream in quite a while.

I like FreeBSD for the breadth of features, but in some cases it feels like they've pushed it to an extreme, a bit of a kitchen sink. I don't think you need three different firewalls, a single good one would do a better job.


I don't know that it's necessarily outdated, more than it's a fork that evolved differently, and I don't think they'll reconverge.

I actively use ipfw and pf (at the same time!) because neither one can do all the things I need. I've never used the third one though.


That's why I prefer OpenBSD vs NetBSD and FreeBSD. Correctness at the core technologies before pushing any new cool feature.

>I don't think you need three different firewalls, a single good one would do a better job.

This.


I'm subscribed to their announcement list (where they publish errata) and I haven't seen anything yet.


IPv6 Extension headers are a nightmare. There are likely lots of bugs lurking in lots of places due to extension headers stacked in unusual ways. A lot of hardware and drivers simply give up on packets with more than a single extension header for this reason.


v6 on the whole just doesn't seem like a well-designed protocol, especially not for the 21st century. It's kind of a shame that the negligible uptake in the 2000s wasn't used to do a go-around and create a more apt successor to v4.


Curious why you think that? IPv4 + ARP + DHCP + NAT has a lot more baggage. IPv6 and a stateful firewall gets the job done quite well, without the address exhaustion.


Ah, where to start ...

128-bit addresses are annoyingly huge. 64 bits would have been enough. Even 48 bits gives you 64 thousand times the ipv4 address space. 64 bits gives you 4 billion times the ipv4 address space. In practice the 128-bit address space has been used as wastefully as it allows e.g. giving a whole /64 to a single server (4 billion ipv4 internets to just a single server!)

Link-local addresses being automatically assigned to every interface, as they are with ipv6 (fe80::xxxx:xxxx:xxxx:xxxx) means that you need to use an interface index or name to distinguish them, so now addresses sometimes need a "%XX" added on the end, e.g. fe80::1ff:fe23:4567:890a%eth2 (this is specific to the source machine, not dest ...)

IPv6 was originally designed to not have DHCP, but in practice we still need DHCP (DHCPv6) in most cases.

There were a bunch of schemes to try to bootstrap ipv6 adoption and they all made it worse. Way back in the 2000s my cable company had some 6to4 servers that worked. Then later there was "teredo" tunneling included in windows vista I think. And there were more. They're all pretty much forgotten now. The problem was that they gave some percent of consumer computers (maybe 2%? maybe 5%?) a false impression of working ipv6, and these computers would hang when trying to access websites that advertised ipv6 addresses in dns responses. So, many websites that had ipv6 at one point, removed it, for many years, until late 2010s ("ipv6 day" etc). This was fixed with the "happy eyeballs" algorithm and other tricks like not returning ipv6 addresses from dns requests made over ipv4 (not sure how widely this was done, but it was done by some significant number of ISPs). Anyway this set back adoption by 10 years probably.

There was even a problem where linux had a sysctl option to automatically listen on a "mapped" ipv6 address whenever a process listened on an ipv4 address, this was automatically enabled on some popular linux distros. Later, when the process tried to explicitly listen on a port on ipv6, it would fail because something was already listening on that port on the wildcard address. So companies had to figure out this issue and disable that sysctl option - but, again, the typical response was "screw it just disable ipv6 everywhere".

I'm typing this from a corporate laptop with ipv6 explicitly disabled even though my current network supports it, because the required corporate VPN doesn't support ipv6. Today.


The 128-bit address complaint is short sited. What does it really matter if the addresses are 128-bit. It ensures we are able to use this protocol for decades. IPv4 space was used wastefully too when it was plentiful. That will correct itself when and if IPv6 addresses become constrained.

I don't really understand your complaint about link-local addresses and why its a real problem.

The whole bootstrap ipv6 adoption stuff was a mess. We can agree there.

There are plenty of shitty bugs in IPv4 handling that still get released in major platforms. Not sure why the sysctyl thing is hard. Anytime you adopt a new feature, service, or platform it requires some critical thinking.


> "screw it just disable ipv6 everywhere"

Troubleshooting step #1. Sad (reasonable, but sad).


ipv6 doesn't give most people the business benefits. These are companies that are perfectly happy with on prem rfc1918 addresses and a bit of srcnat, and indeed are likely reducing that space requirement today as more stuff moves into 'the cloud'

Why spend money trying to get ipv6 work when your laptops work fine with a 192.168.x.x range


On the other hand, even something as easy as ULAs would have saved a former employer of mine three+ months of effort in network renumbering (and other directly-related resource management activities (like, suchas, deciding "Is it more trouble to renumber this, or merely turn it off and deal with having a much, much shittier replacement?")) planning after a corporate merger.


It's almost certain you'd have deployed a dual stack ipv4 and ipv6 internal network so you'd have to re-number the ipv4 part anyway, and still probably end up with a mess with ipv6.


Why would you make the internal network dual stack? Now you need to two sets of firewall rules, and devices have two protocols to reach each other making debugging unnecessarily difficult.

Most traditional internal networks are IPv4 only. In larger tech companies where 10.0.0.0/8 isn't enough, internal networks are IPv6 only. Only a tiny number of Internet-facing servers (like your load balancer / reverse proxy for external traffic) should be dual-stack.


> It's almost certain you'd have deployed a dual stack ipv4 and ipv6 internal network...

For the ones that needed Internet access, sure. But, a huge chunk of these machines were machines that never, ever, ever talked outside of the corporate intranet, so they never needed an Internet gateway, and NAT was never an issue. Assigning these boxes an address from a ULA would have worked just fine.

> ...you'd have to re-number the ipv4 part anyway,

As mentioned above, for the machines that did need to talk to the Internet (which required them to have v4 addresses) yeah, sure.

> ...and still probably end up with a mess with ipv6.

I don't see how this follows from what you said.

The way you generate ULA prefixes means that you're highly unlikely to ever have to renumber ULA-using networks that you want to merge. Do you have specific addressing perils or pitfalls in mind?

(Bear in mind that you're talking to someone who has been happily using IPv6 at home for twenty years, and someone who's quite aware that companies like Comcast, T-Mobile, and a bunch of other telecoms run IPv6 on their infrastructure (and often their customer-facing) networks, trouble-free, and have been for many, many years.)


> I'm typing this from a corporate laptop with ipv6 explicitly disabled even though my current network supports it, because the required corporate VPN doesn't support ipv6. Today.

And (today) my (mandatory) corporate VPN doesn't support ipv6, but my both laptop and the VPN work just fine when the machine has one or more IPv6 addresses.

I'm having a somewhat difficult time imagining what series of misconfigurations were required to make your corporate network fail in that way.

Anyway. I've been using IPv6 continuously (whether via Teredo, an explicitly-configured 6to4 tunnel, or native dual-stack) for (ugh) nearly twenty years. IME, it works fine, really.


How about the fact that half the RFCs you were supposed to implement 20 years ago have been superseded by RFCs saying do not implement?


Not sure why you are being downvoted, if there was a pile of churn in IPv6 recommendations I'm curious about them.


* SLAAC with MAC addresses -> Stable privacy addresses

* fec0:: site local addresses -> ULAs

* No DHCP handing out addresses -> DHCPv6

* "IPv4 compatible" ::<IPv4 address> -> "IPv4 mapped" ::ffff:<IPv4 address>

* 6to4 -> Just use dual stack

* ip6.int RDNS -> ip6.arpa


RH0 was so bad it should count twice.


I think it's probably just the fact that the IPv4 stack has just received a lot more hardening because it's deployed everywhere (by necessity)... and IPv4 has had a 15+ years lead over IPv6 on that whole hardening thing because it came later and a time where IPv4 was already pretty well established.


Not OP and certainly not in the anti-IPv6 camp.

I'm wondering though: could you build a case that under IPv4, a misconfigured NAT would only result in lost connectivity for nodes behind the router, while for IPv6 a misconfigured firewall and worse triggered through a vulnerability, would then result in protected nodes being exposed?

I know NAT-PMP (port mapping) vulnerabilities exist, allowing external actors to set port mappings to hosts behind NAT, but this seems a bit harder to exploit than a bypassed firewall.


I don't think that's true in general because each of these end-user routers have their own sharp edges. IPv4 consumer routers have a DMZ option which would, for at least 1 device, be the same as taking down your stateful firewall. Also, thankfully, in all of the examples I've seen in the wild, the stateful firewall was just on by default, much as NAT is on by default. In both cases you are taking steps to compromise your own security, that most people won't bother to do.

Finally, the risk to an individual machine 'loose on the internet' is lower than its ever been because Windows has for years enabled a firewall by default on its own, and macOS doesn't expose any open ports by default either. That does leave printers, IoT devices, and the like, but now we're really pretty far into the weeds of lots of non-default customization combined with individual CVEs in non-computing hardware.


If my firewall failed then the packet won't reach my 192.168.0.1 DMZ server as it will likely never be translated from my real 12.34.56.78 IP address (as the translation would be part of that stateful firewall)

Sure there are exceptions, but you are massively reducing your risk by not having your toaster having a public address by default and having something actively have to translate it to a public address


Isn't NAT the only real difference? In IPv6 you get NDP instead of ARP, but you generally still need DHCPv6 for many kinds of networks. So you have IPv4 + ARP + DHCP + NAT, vs IPv6 + NDP + DHCPv6. Not that much of a difference. Especially since, for a household user, there is actually pretty little difference between NAT and just a stateful firewall.


Actually, if the router supports RDNSS (DNS info in RA), SLAAC is sufficient for household users -- no need for DHCPv6.


Sure for an intranet. Know of any ISPs handing out addresses in slacc? I sure hope not as the rfc (too lazy to find who CV) stipulates resi users should get bigger than a /64.

So now we have two types of network addressing depending on which type of network! So simple.

All of this is ignoring the absolute madman icmpv6 vulns discovered over the last few years that are generally allowed through do to ndp using icmp.

V6 sucks and this is coming from someone who lived and breathed it for years. I do not run it on my sensitive installations.


> > > Not that much of a difference. Especially since, for a household user, there is actually pretty little difference between NAT and just a stateful firewall.

> > Actually, if the router supports RDNSS (DNS info in RA), SLAAC is sufficient for household users -- no need for DHCPv6.

> Sure for an intranet. Know of any ISPs handing out addresses in slacc?

It's a bit odd to reply to two folks talking about residential LANs with "Yeah, well, what about what ISPs do, eh?!".

Reading through the relevant RFCs leaves me pretty sure that SLAAC works for prefixes larger than /64... you just won't get split that into subnets that your router delegates to the LAN side of things.


It’s a bit odd to leave out the most exposed component of your residential lan when discussing its simplicity. Are you expecting never to touch the external interface of your residential lan?

Then you are reading the “rfcs” wrong.

What you really want to put in to your search engine is “does slacc do prefix delegation”.


> What you really want to put in to your search engine is “does slacc do prefix delegation”.

As I said:

> ... you just won't get [to] split that into subnets that your router delegates to the LAN side of things.


prefix delegation is more than just splitting a larger prefix into smaller prefixes Have a nice night!


kek


I would be embarrassed too if I was trying to act like slacc can hand out a 64 so I understand why you are defensive


not the original poster but i want to chime in, the address is just poor. an IPv4 address is decent to remember and while DNS is useful, the issue sometimes is DNS, in which case you need the IP anyway.

12:141:::2315:14 or whatever is ugly and terrible syntax. firstly...

1. why colons? if you're typing in an IP address, you might also have to type in a TCP/IP port in colon format, why did IETF think overloading this was a good idea? it also makes the address scheme look ugly. the ways of getting around this by using brackets just look plain awful.

2. why do it in hexadecimal format? there are now 16 characters in each IP digit. i'd rather have (if we really need 128-bit addresses, which since we give out /64s, seems not to be the case) it be in dotted decimal. maybe even make the dotted decimals 16 bits if it's really an issue. do get rid of the myraid of other stupid ways to write IPs though, dotted decimal could easily be standardized.

3. DHCP is a good thing, why is it maligned? a central source of truth who is what is great, at the network level I can say "hey this person has the IP of X." it seems like a much better idea than SLAAC ever was.


IPv4 allocated prefixes on 8-bit boundaries, so dotted decimal made sense at the time. CIDR in 1993 made the prefix boundaries arbitrary, which required "difficult" math to convert between binary and decimal.

So the point of hexadecimal is to make CIDR easier. Consider the sequence of 1s followed by 0s:

    dec: 0 128 192 224 240 248 252 254 255
    hex: 00 80 C0 E0 F0 F8 FC FE FF
Once you've adopted hex, dots become a problem: is "1.1.1.1.1.1.beef.de" a domain name or an IP address? Perhaps they could've chosen something other than :, but I'm not sure what. Maybe require every IPv6 address to contain .. somewhere?

I don't really have strong opinions on DHCP vs SLAAC.


> an IPv4 address is decent to remember and while DNS is useful, the issue sometimes is DNS, in which case you need the IP anyway

It's like rambling about absence of crank handle on modern cars.

> why colons

Because dots are in the DNS.

> why do it in hexadecimal format

Because it's shorter than decimal and you can't nest decimal representation without some delimiter, eg 1220 -- is this 12 20 or 122 0 ? Cue in 'but why colons'

> DHCP is a good thing, why is it maligned? a central source of truth who is what is great

No, it's not. And definitely it's not source of truth. A client can ask, DHCP server can provide an address but if you don't have an address in DHCP leases that means nothing. And even if you have that doesn't mean that this is still the same device.


Fragmentation is a nightmare. There's been lots of unexpected interactions and security bypasses with that over the years.


Fragmentation is a nightmare in a nightmare: we also discovered that IPv6 fragments reassembly (as implemented by major operating systems) is still plagued by the problem of overlapping fragments. Potentially, you can still bypass IDS/IPS using the same techniques from IPv4...

Shameless plug: we will present these results at ESORICS 2023 :-)


IPv4 fragmentation was even worse since any device in the middle could fragment packets. IPv6 atleast limits it to the client/host. I still think they should have designed IPv6 to include L4 info in each fragment to avoid having to reassemble to get that data.


The final rule:

  pass in  quick on $ATTACKER_IF inet6 label "Allow the rest of IPv6"
should probably be

  pass in quick on $VICTIM_IF inet6 label "Allow the rest of IPv6"
right?


Author here. The ruleset in the blog post is correct. The rationale of the example ruleset is the following: we want to block TCP, UDP and ICMPv6 traffic from the attacker, while allowing other protocols.

Note that IPv6 packets are matched against all rules, while IPv6 fragments are matched against rules that contain network-level information only (as fragments don't have upper layer headers, except for the first fragment).

If the scrubbing is enabled, then `pf` is supposed to reassemble all fragments, so that there is no more fragmented traffic (= all rules are applied to all IPv6 packets). Normally, it works.

In this case, we tricked the firewall by sending an "atomic fragment" that is composed by multiple fragmented headers (this is forbidden by various RFCs). These headers trigger the reassembly mechanism of `pf`, but the packet is "re-assembled" only once: when it enters the rule matcher (after the reassembly), it is still considered a fragment, and all rules with transport-level (and higher) protocol information are skipped.

So, the "block-pass" pair at the end is used to exploit this behavior (in other words, we can decide which rule we match by playing with IPv6 fragment header).

PS: an "atomic fragment" is a IPv6 packet that is fragmented using only one fragment. Surprisingly, it is supported by RFCs.


Thank you for the response! I read "allow the rest" to mean "the rest of everything", rather than "the rest of the protocols".

Based on your explanation, does that mean if the restriction was

  block in quick on $ATTACKER_IF inet6 label "Block all connections from the attacker"
it would not succumb to this vulnerability? Great job with this, btw.


> We reported the vulnerability at 2023-07-12 20:15:43 UTC and received the ACK at 2023-07-12 01:34:54 UTC.

I am not sure the timeline...


Clearly FreeBSD takes security so seriously that they have a time machine used solely for verifying security disclosures.


Ooops! Clearly a typo :-)

I've fixed it, the cached version should expire shortly.


And that's why I disable IPv6 in my home network. Don't need it's benefits, and don't need the surprises it might bring




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: