Early in our testing we noticed that the firewalls handled their state tables in surprisingly different manners. Some used twice the memory for each connection when performing NAT, and some seemed to handle almost infinite tables while others had hard limits on connection table space. Intrigued, we cooked up some tests to evaluate what, under the hood, each firewall considered TCP "state."
We figured that at minimum, any firewall filtering packets based on the state of TCP sessions transiting it would have to look at: the IP addresses of the hosts communicating, the port numbers on each end of the connection, the TCP headers' compliment of SYN, ACK, RST and FIN flags as used in connection setup/handshake, flow and teardown, and the flow of packets making, continuing and tearing down the connection.
Finally, we thought that, because TCP sequence numbers are the key to TCP reliability and connection flow, the firewalls should be scrutinizing or even manipulating these numbers.
The results were a mix of expectations met and surprises had. Cisco's PIX 535 and NetScreen's 1000 employ robust TCP state tables tracking IP addresses, ports, TCP flags seen and sequence numbers when checking a midsession packet's acceptability against the list of "open" allowed connections. The rest of the firewalls tested clearly did not take TCP sequence numbers into consideration when checking a packet's acceptability.
Why care about TCP sequence numbers? After all, most hosts can fend off bogus packets without losing a valid connection. Yet a firewall is supposed to be a security device -- a hardened gateway through which traffic to more vulnerable systems must pass. The more a firewall works to enforce RFC-compliant traffic -- while handling the load -- the more likely it will block complex packet-level attacks before they're widely known.
So what do the test packets in the chart ("TCP Shenanigans Test") tell us?
>> Test 1 (Block ACK with good port numbers but bad sequence numbers) tells us whether the firewall checks sequence numbers on ACK packets at all. The firewall should block these packets.
>> Test 2 (Permit ACK with in-win sequence numbers) tells us whether the firewall is being too strict with ACK packets, which can arrive out of order but within the acceptable window. The firewall should accept these packets.
>> Tests 3 and 4 (Block RST with good port numbers but bad sequences numbers and permit RST with in-win sequence numbers) check whether the firewall handles RST (connection abort) packets any differently from ACKs. The firewall should block packets in Test 3 and accept packets in Test 4.
>> Test 5 (Block ACK with bad source port and bad sequence numbers) checks whether the firewall keeps "state" for connections to a service behind it, or whether it is functioning as a basic packet filter for such services. The firewall should block these packets.
-- Mike Scher, mscher@neohapsis.com