On Fri, Jan 07, 2005 at 11:06:18AM -0500, Dave Anderson wrote:

> I hadn't realized it until I started thinking this through, but it
> appears that, if floating state is enabled, there's no way to prevent
> PF from passing *some* spoofed packets -- though this probably isn't a
> significant issue in practice.  Perhaps the "right" way to deal with
> all of these issues is to provide more explicit control over floating
> state -- e.g., eliminate the current general floating state and add to
> each rule specifying "keep state" (or its relatives) an optional list
> of interfaces to which those states may float with a direction for each
> such interface.

Adding to the previous explanation, if you know that one side of the
connection should pass only through one specific interface (like a
single uplink interface), you should use an if-bound state for that
side. There's no reason to use a floating state in that case.

If you're using a floating state (maybe just because it's the default,
and you didn't realize the difference), there is one form of spoofing
that becomes possible:

The state entry says:

  on any interface, pass incoming from A to B, outgoing from B to A

Such packets should only occur on interface I, but you made the state
floating (instead of if-bound to I), so theoretically, someone might
inject a packet on another interface (not I), like

  incoming from A to B on J
  outgoing from B to A on K

but NOT

  incoming from B to A on L
  outgoing from A to B on K

because the state will only match the former two, but not the latter
two.

Now, to successfully match a state entry, an attacker needs to know (or
guess) more than just the source and destination addresses. For TCP, he
needs to know both ports and, more importantly, the current sequence
numbers. We rely on the unguessability of sequence numbers, only the
endpoints of a connection (and the few legitimate hops along the path
between them) know these secrets. Obviously, if an attack were able to
guess the secrets, he could attack your connections in a number of ways,
anyway.

So, try to think of a case where an attacker gains any advantage by
being able to pass a packet

  incoming from A to B on J
  outgoing from B to A on K

where he knows the connection secrets and couldn't just as well pass the
packet on I (where it would pass, anyway). I guess it would have to be
some very specific case where, for some reason, the attacker can only
inject packets on interfaces other than I.

I haven't seen a single example where this would matter in practice.
But, yes, if worry about this, make your state if-bound to I, and this
becomes a non-issue.

My guess is that we might eventually switch to if-bound as default. I'm
in favor of changing all examples in documentation to use it explicitely
until then. But if anyone is claiming that the default of floating
states leads to holes in rulesets of people unaware of the issue, I'd
like to see an practical example attack.

Daniel

Reply via email to