SecurityFocus interviews three OpenBSD developers about their network stack protection against DoS ICMP attacks, a short comparison with Linux' stack, and some thoughts on OpenBGPD.
On November 1st, OpenBSD 3.8 will be released. This is the first release that includes protections against some old and simple DoS attacks via ICMP. How do these protections work?
Fernando Gont: First of all, I'd like to make a comment on that of "old attacks." The attacks are old, but there have never been proposals on how to deal with them. So we are talking about old attacks which are still current. If you look at NISCC's or CERT/CC's vulnerability report, you'll see that virtually every vendor/system is affected by either all or some of these ICMP attacks. It's 2005, and most systems are still vulnerable to ICMP-based attacks. Scary, isn't it?
There are basically three different attacks that can be performed against TCP by means of ICMP: blind connection-reset attacks, blind throughput-reduction attacks, and blind-performance degrading attacks. There are general counter-measures that you can implement for ICMP-based attacks, and attack-specific ones. In OpenBSD, we implement both.
The general counter-measures are based on performing checks on the received ICMP messages. Basically, we check that the TCP sequence number contained in the ICMP payload corresponds to data already sent but not yet acknowledged. The rationale is obvious: if the TCP sequence number contained in the ICMP payload corresponds to data already sent but already acknowledged, then the error message must have been forged, caused by an old TCP segment, or corrupted, and thus should not be honored. If the TCP sequence number contained in the ICMP payload corresponds to data not yet sent, then the error message must have been forged, or corrupted, and thus should not be honored, either.
This is a general validation check for ICMP messages. However, it doesn't eliminate the vulnerabilities: it just requires more work (or luck) on the side of the attacker. Therefore, in OpenBSD we implement, in addition to this general validation check, attack-specific counter-measures that completely eliminate the vulnerabilities.
The blind throughput-reduction attack is performed by means of ICMP Source Quench messages. These messages were originally introduced for flow control and congestion control in IP networks. An attacker can use ICMP Source Quench messages to fool the attacked host into thinking the network is congested, and as a result, the attacked system will reduce the rate at which it is sending information. However, if you look at it carefully, TCP implements its own flow-control mechanism, and thus does not rely on ICMP Source Quench messages for performing flow-control. Also, ICMP Source Quench messages have been considered for a long time to be ineffective and unfair for controlling congestion. Thus, the counter-measure for the blind throughput-reduction attack is very simple: ignore ICMP Source Quench messages meant for TCP connections.
The blind performance-degrading attack is an attack against the Path-MTU Discovery mechanism implemented by TCP. Basically, an attacker will send a "fragmentation needed and DF bit set" ICMP error message that advertises a small Next-Hop MTU to the victim host, to fool it into thinking it is sending packets that are too large to be forwarded without fragmentation. As a result, the attacked system will reduce the size of the packets it sends, accordingly.
The counter-measure we implement for this attack works as follows. First, we keep track of the largest packet size that has so far been sent for this connection. If the Next-Hop MTU claimed by the ICMP error message is larger than that size, then we simply ignore the error message. Second, we keep track of the largest packet size that has so far been acknowledged for this connection (say, "maxsizeacked"). This allows us to divide Path-MTU Discovery into two phases: Initial Path-MTU Discovery, and Path-MTU Update. This two-phase separation allows us to quickly discover the Path-MTU for a fresh connection (and thus not affect interactive applications), while still being resistant to the discussed attack.
Whenever we receive an ICMP "fragmentation needed and DF bit set" (and provided it has passed all the general validation checks), we compare the advertised Next-Hop MTU with "maxsizeacked". If it's larger than "maxsizeacked", then it means we are in the Initial Path-MTU phase (that is, we are trying to find out the Path-MTU of this connection for the first time), and thus honor the ICMP message immediately. If the advertised Next-Hop MTU is smaller than "maxsizeacked", then it means we are in the Path-MTU Update phase, trying to change the assumed Path-MTU for this connection. In this phase, we should be much more cautious when processing ICMP messages. The error messages could be legitimate (and sent because the packets that correspond to the connection are now being forwarded through a different Internet path), or they could be part of an attack. If the error messages were legitimate, then the corresponding data (those claimed by the TCP sequence number contained in the ICMP payload) should have been dropped by the Internet router that sent the ICMP error message. Therefore, we wait for an RTO (TCP's retransmission timeout), and see if the corresponding data gets acknowledged. If the corresponding data times out, then it means the error message must be legitimate, and thus we honor it, updating the Path-MTU for the connection accordingly. If while we are waiting for a RTO those data get acknowledged, then it means our data are still getting to the remote system, and thus the ICMP error message must have been forged. Therefore, we simply drop the ICMP error message we had received.
The implication of this counter-measure is that in order to perform the blind performance-degrading attack, the attacker should be a "man in the middle," and should be not only lucky enough to hit the TCP window, but should also be able to selectively drop the packets that correspond to the attacked connection. This is so that either the data segments don't get to the remote endpoint, or the TCP acknowledgements sent by the remote end-point don't get [to] the attacked system. If an attacker were able to do this, he would have already DoS'ed the connection, and thus wouldn't have the need to perform the attack.
As for the blind connection-reset attack, BSD-derived implementations are not vulnerable to it. BSD-derived systems never abort established connections in response to ICMP messages. This has been the traditional BSD behavior for quite a long time.
Is there already any other OS that includes them?
Fernando Gont: OpenBSD has been the first operating system to implement a complete set of counter-measures for ICMP-based attacks. Following OpenBSD, NetBSD fortunately ported OpenBSD's counter-measures to their system.
Other systems have followed us, implementing only some of the OpenBSD counter-measures. Unfortunately, it seems they have failed to understand the importance of the counter-measure for the blind performance-degrading (PMTUD) attack. Some vendors/projects simply seem to think that the TCP sequence number check is enough to protect a system from this attack. Others simply wanted to see a working (and tested) implementation, and were not willing to take the lead. At the c2k5 Hackathon we implemented the counter-measure for the PMTUD attack, and tested it extensively. So there I think are no more excuses to vendors: they can follow us, or continue ignoring the problem.
What about Linux?
Fernando Gont: In the same way as BSD-derived systems, they were already treating the so-called ICMP "hard errors" as "soft errors," so they were not vulnerable to the ICMP-based blind connection-reset attack.
Linux had also been implementing the basic TCP sequence number check for several years.
When I published my IETF internet-draft "ICMP attacks against TCP," they removed support for ICMP Source Quench messages, as recommended in my draft. They were very responsive on this particular fix.
However, they have not yet implemented the full counter-measure for the PMTUD attack. They basically said they first wanted the counter-measure to be tested. So maybe that now that OpenBSD ships with this counter-measure, and that NetBSD has followed us, they will finally implement it.
The counter-measure for the PMTUD attack is particularly important. First, because those ICMP messages used for PMTUD are probably the only ones you cannot filter. Second, because even if you protect your TCP connections by means of the TCP MD5 option, or by means of IPSec, you still need the Path-MTU Discovery mechanism. And, at that point, PMTUD becomes "the weakest link in the chain".
There are scenarios in which IPSec-secured connections could get frozen by means of the PMTUD attack. If you count the number of bytes required for headers (IP+IPSec+TCP), along with the number of bytes required for IP and TCP options, and realize that the minimum IPv4 MTU is 68 (i.e., a "fragmentation needed and DF bit set" ICMP message can report a Next-Hop MTU as small as 68 bytes), you come to the conclusion that the attacked connection could become frozen, or the TCP/IP stack may end up behaving in some unexpected manner.
I must acknowledge that Alan Cox and David S. Miller read the draft, and took the time to provide feedback and contribute to make my internet-draft a better one. This is something I appreciate. Most other vendors/projects didn't care to provide feedback, or anything.