This is a version of a writeup I did for the BroadbandReports security forum.
The technical details of the TCP/IP core vulnerability are out, and they can be found here. As has been the case before, it's not so much a flaw in the protocol itself as it is in the implementation of the protocol, and I'm not sure I'd even call it a bug.
Short description: existing TCP/IP implementations do not validate enough of the RST packet before accepting it. Though they all seem to look at the sequence number, they do not also consider the acknowledgement number, so it's much easier to forge a RST.
This has all been talked about in terms of BGP, but it's not strictly a problem with that protocol. What happens is that the consequences of "interrupted TCP connection" can be much higher with BGP sessions than with others.
Long description:
In all TCP/IP conversations, each side keeps track of how much data it sends and receives with two counters, and they're exchanged on every packet sent. The packet my end sends you includes:
When a packet is received, I check to make sure that the sequence number in your packet is what I expected: if it's too high, then a packet must have gotten lost. If the sequence is too low, then a packet got sent twice. There are mechanisms for dealing with these situations, and it's all routine stuff.
The "window size" is meant to limit the amount of data "on the wire" at any given time: if you tell me that your window size is 16kbytes, then I'll never send more than that to you. As soon as I get an acknowledgement for some data I sent earlier, this "opens the window" so I can send you some more. This also happens automatically.
Enter the RST. This is a "reset", and it's meant to abandon connections in process.
The most common situation is when a computer receives a connection request for a TCP port that has no listener (e.g., an inbound request for 80/tcp when there is no web server). To let the caller know that there ain't nobody home, the computer sends an RST packet to indicate "Connection refused" unless I'm ignorant and run "stealth", in which case I return nothing.
It's also used to abandon a connection that actually is in progress.
Let's say that your computer and mine are having a TCP conversation, but my end crashes BSOD - grumble. When your computer sends a packet to me after I'm back, my TCP stack won't have any record of our conversation: What the hell is *this*? So my end sends a RST to you so you shut down the conversation properly.
At this point we've just had "TCP/IP 101", and there is nothing in here really related to security. Let's talk about sabotage.
The gist of this issue is that third parties can inject an RST packet in an existing conversation and fool them into disconnecting.
If I'm sitting on the side thinking about mischief, I have to first identify a TCP conversation in progress. In order to have my fake RST considered, I must have at least these four pieces of data:
If all I had to guess was the source IP+port and destination IP+port, it would be utterly trivial to reset anything, but the RST packet also contains a sequence number. If the sequence number is "outside the window", it's rejected as being invalid, but the larger the window gets, the easier it is to make a lucky guess and fall inside.
Originally TCP had a max window of 64kbytes (which is pretty tiny compared to a 32-bit sequence number), so you have to do a LOT of guessing to fall in the window, but if you turn on Window Scaling, you can have much much larger windows. Guessing is not that hard in this case (even though BGP typically doesn't need or use large windows).
Note that I'm still not finished, but I need to take a detour.
Most TCP/IP connections are very short-lived, and have limited consequence if they are interrupted. It's annoying if I have my telnet or ssh session reset - I just reconnect. Where this matters is in BGP, the Border Gateway Protocol, which is the routing/peering protocol for internet backbones.
In BGP, two backbone routers set up a TCP/IP connection between themselves and spend all day exchanging route information back and forth. This is a point-to-point connection (only one hop), and the connection stays up forever for this chitchat.
But if one end sees that the other end went away, it assumes that not just the BGP session is gone, but the whole link, so it drops all routes that go through that link. The link is still good, of course, but the routers don't know it, so this is terribly disruptive while the route tables are reconstructed. This kind of thing is called a "route flap".
The two routers will reconnect right away and start talking again, but then "dampening" enters the fray. If a router sees that another is flapping too often, it can start to ignore it for longer and longer periods of time. This is a self-protective measure so it won't spend all its time rebuilding router tables for connections that come and go.
"Route flapping" and "dead links" are both very painful at the backbone level, and big problems in one area have a way of spreading. I'm not BGP guy, but a friend of mine who is said "flapping on the East coast can f*ck the entire world".
So we all can see that BGP has very far-ranging ramifications for interrupted TCP connections, so we turn back to the flaw that makes it interesting.
I mentioned earlier that guessing the sequence number is not terribly hard, and I'll make a side note that this is not the same as guessing the initial sequence number - here we only need to be within the window.
It turns out that RFC793 - Transmission Control Protocol specifies the contents of not just the sequence number of an RST packet, but of the acknowledgement number too. When a TCP stack receives an RST, it can perform validation checks on both of these values, and guessing both is very very hard from the attacker's point of view.
Most TCP/IP implementations apparently do not perform both of these validations, which makes the attacker's job much easier. In a non-hostile environment, there is no real need to do this kind of checking, but we're not in one of those environments.
So these router vendors have all been scrambling to to add this kind of checking to their products, and my guess is that it's been really ugly. Just getting the code right itself is one thing, but these RST packets - even valid ones - are coming from other systems, and if you have some "other" computer that sends malformed RST (e.g., improper ack number), then suddenly your end breaks too. It must have been a mess to coordinate and test.
Time will tell if other router vendors - even low-end ones - will step up and make this fix. Right now the only real "interesting" affected protocol is BGP, but I think it's likely that others will emerge as well.