TCP Split Handshake: Why Cisco ASA is not susceptible
As I told yesterday, I was not very satisfied with the updated NSS remediation guide concerning the TCP Split Handshake issue, published after the second round of testing on Cisco and Fortinet devices.
In particular, in case of Cisco, in my opinion the report was poor on details, considering Cisco’s ACL approach suboptimal and definitively coming to the discouraging conclusion that:
Our original results are unchanged, and ultimately Cisco did offer some mitigation steps.
This is clearly in contrast with what stated in the official Cisco post, which declares Cisco ASA firewall not susceptible to the issue, even if, in my opinion, the most disappointing aspect of the story consists in the fact that no other detail is provided on the NSS document, leaving many unresolved questions about the real nature of the issue and the level of vulnerability of Cisco devices.
Since I was really curious to discover were the truth resides, I decided to ask to Cisco Engineers to provide more details on the testing results, and after few hours it is exactly what they kindly did with an accurate and detailed description of the events posted by Joe Karpenko and Omar Santos, the two engineers who took part to the joint session with NSS Labs.
There are 2 connection establishment handshakes associated with this topic, they are as follows:
* Split Handshake (primary concern/issue)
* Simultaneous Open
By default, the Cisco ASA accelerated security path (asp) prevents both the “Split Handshake” and “Simultaneous Open” using the “tcp-dual-open” connection check. The Cisco ASA firewall drops the TCP SYN segment sent from the server (eg: fakestack.rb) when there is an embryonic TCP connection already open between two endpoints.
However, NSS created and demonstrated a brand new test-case which deviates from the 2 connection establishment handshakes mentioned above along with the most commonly used 3-way handshake. This new test-case is not compliant with the TCP connection establishment equirements defined in RFC 793.
For the “Split Handshake”, the first TCP segment sent by the server (fakestack.rb) in response to the clients TCP SYN segment is a TCP ACK segment (also described in the paper, The TCP Split Handshake: Practical Effects on Modern Network Equipment, pg. 200). However, for the new test-case a TCP RST/ACK segment is sent instead. At this point the client would be in a state called SYN_SENT and the server in the SYN_RCVD state.
The protocol specifications for TCP (defined in RFC 793) define how to process TCP segments received in certain states. When an endpoint is in a SYN_SENT state and it receives a TCP RST/ACK segment the endpoint aborts and closes the connection.
During our testing, the client ignores the TCP RST/ACK segment sent by the server (fakestack.rb) and does not abort the connection. Upon seeing the TCP RST/ACK segment sent by the server (fakestack.rb) the Cisco ASA firewall tears down the connection slot. Immediately following the TCP RST/ACK segment sent by the server (fakestack.rb) it sends a TCP SYN segment which initiates a *new* connection establishment and completes a 3-way handshake that complies with the TCP specifications defined in RFC 793.
For the new test-case, access control list rules can be applied using an access-group and used as additional countermeasures to mitigate and prevent unsolicited connection attempts between the endpoints for a TCP conversation when the client does not abort the connection as defined in the RFC protocol specification for TCP.
Given this description of the events, I completely agree with Cisco’s interpretation and I definitively believe there is nothing strange about the behaviour of the ASA firewall, since it immediately tears down the connection slot upon receiving a TCP RST/ACK (how it should be), and immediately allocates a new connection after receiving the new TCP SYN from the server.
Moreover, in the testing scenario the client behaviour does not fit with the TCP RFC. As a matter of fact, page 32 of the TCP RFC 793 states that:
The principle reason for the three-way handshake is to prevent old duplicate connection initiations from causing confusion. To deal with this, a special control message, reset, has been devised. If the receiving TCP is in a non-synchronized state (i.e., SYN-SENT, SYN-RECEIVED), it returns to LISTEN on receiving an acceptable reset. If the TCP is in one of the synchronized states (ESTABLISHED, FIN-WAIT-1, FIN-WAIT-2, CLOSE-WAIT, CLOSING, LAST-ACK, TIME-WAIT), it aborts the connection and informs its user. We discuss this latter case under “half-open” connections below.
Not only. Page 37 of the same RFC, on the paragraph “Reset Processing” states that:
In the SYN-SENT state (a RST received in response to an initial SYN), the RST is acceptable if the ACK field acknowledges the SYN.
Which is exactly the occurrence in the above scenario when the client receives the TCP RST/ACK.
The sum of the two assertions definitively means that the tested scenario is probably not fully compliant to RFC 793 since, as stated by Cisco Engineers, upon receiving the TCP RST/ACK from the server, the client should reset the connection, free the socket and revert to LISTEN state, which corresponds, according to RFC 793, to a state waiting for a new connection request from any remote TCP and port.
And even if could be acceptable to perform a test in similar conditions not covered by the RFC 793, similarly I do not find anything strange or suboptimal in deploying ACLs to prevent unsolicited connection attempts between the endpoint. As I told yesterday, a firewall should protect critical assets from unsolicited connections independently from the risk of a TCP Handshake attack…
Again, I would like to thank the Cisco Engineers for their kindness and the transparency with which they quenched my curiosity thirst.
P.S.: A final thought from my youth
Now the big picture is clear! Few years ago, when I was younger and at the end of my short and shining system engineer life, I stumbled upon the curious case of a custom application which suddenly stopped to work after an upgrade of the firewall. Deeper analysis showed that each session of the application used the same TCP port for source and destination (the port number was used to identify the customer sigh!). Moreover the server used to terminate the connection with a TCP RST/ACK and to immediately open a new connection with a SYN packet with the same source and destination port number of the previous session. Does it sound familiar to you after reading the post? Yes it does! At that time we spent many hours on insulting the dangerous mind of the programmer and his strange interpretation of the TCP-IP RFC (but the client port should not be allocated on the random Ephemeral Port Range from 1024 to 65535?). After many years I got it!: he was a precursor of the TCP Split Handshake attack.
You will be asking which was the firewall that since then proved not to be susceptible to TCP Split Handshake… I will never say it! Not even under torture. I only may say that in order to fix the problem we had to perform a very unlikely tuning on the timeout parameters of the firewall queues…