# Why is TLS susceptible to protocol downgrade attacks?

A recent blog post from Ivan Ristić (expert extraordinaire on all things SSL) says:

all major browsers are susceptible to protocol downgrade attacks; an active MITM can simulate failure conditions and force all browsers to back off from attempting to negotiate TLS 1.2, making them fall back all the way down to SSL 3. At that point, the predictable IV design is again a problem. Until the protocol downgrade weakness is fixed, newer protocols are going to be useful only against passive attackers, but not against the active ones.

Why is this? Why is TLS vulnerable to this?

I know that SSL 3 included special mitigations to prevent protocol downgrade attacks where a man-in-the-middle downgraded two SSL3-capable endpoints so they end up using SSL 2. This protection in SSL 3 was critical, because SSL 2 had some major problems, and if you could downgrade both endpoints to SSL 2, nasty attacks would have become possible. Happily, the SSL 3 designers anticipated this risk in advance and made sure to introduce a special mechanism in the protocol to prevent "downgrade-to-SSL2" attacks.

So how is it that TLS ended up without any mitigation to prevent downgrade from TLS 1.2 to TLS 1.0 or even to SSL 3.0? Is there some reason why it is non-trivial to add downgrade protection? Did the TLS standard committee just overlook this one? Or, was it considered a low priority? Is there a straightforward way for future versions of TLS to address this issue?

-
... possible NSA influence? –  Richie Frame Sep 21 '13 at 6:52

Short answer: Because the browser developers have long thought interoperability to be more important than security and standard compliance.

Slightly longer answer: Some SSL/TLS server implementations do not negotiate the protocol version correctly, but terminate the connection with a fatal alert if the client attempts to negotiate a protocol version that the server doesn't support. This might happen at either of three steps in the handshake protocol:

1. When the server parses the client hello (which should contain the highest protocol version supported by the client). A correctly implemented server should store the client version value, even if it is not supported by the server.
2. When parsing a client key exchange message containing a RSA encrypted pre master secret (which should contain the highest protocol version supported by the client as the first two octets). This version field should be compared to the client version value above, and not to the negotiated version.
3. When verifying the client finished message (which should be a hash of all handshake messages, including the client hello which contains the highest protocol version supported by the client).

Now, if the server for some reason doesn't process these steps in accordance with the TLS 1.0, 1.1 or 1.2 standards, but one way or another e.g. requires the highest protocol version supported by the client to have a specific value, or to be no greater than the highest protocol version supported by the server, the client has two choices: Either fail the connection with an error message that is displayed to the user, or attempt to connect again with the highest protocol version disabled.

The exploit is possible if the client uses the second alternative (which e.g. Chrome does, but not IE 10). Even if the authentic server actually supports TLS 1.1 or TLS 1.2 and the authentic server actually does handle the client version value correctly, the MITM might exploit that the client doesn't know which server handles the client correctly or not, and inject alerts in both directions to get the client to reconnect using a lower version.

Edit: For completeness, I should add that I concur with @Thomas in his answer that this should largely be a non-issue, simply because:

• Trivially, even under a MITM attack that exploits this behavior, neither the client nor the server will be able to negotiate a protocol version they don't enable, and
• Neither the client nor the server should enable protocol versions that don't provide adequate security.

The underlying problem is not really that some clients negotiate the protocol version in a way that is not strictly supported by the standard, in order to be able to connect to servers that might or might not negotiate the protocol version in a way not strictly supported by the standard.

Rather, the problem might occur in situations where Carol might connect to multiple servers, but TLS 1.2 is only required for the connection to Sue, for all other servers SSL 3.0 is sufficient. Conversely, Sue might accept connections from multiple clients, but it is only the connection from Carol that requires TLS 1.2. Ideally, Carol and Sue should be able to rely on the protocol negotiation to ensure that TLS 1.2 automatically gets negotiated (and in such case they might, or might not, be vulnerable to the exploit), but correct implementations should really check that the TLS connection meets the minimum security requirements after it has been negotiated.

-

Annex E.1 of RFC 5246 contains the following text which is a nice summary of the situation:

Note: some server implementations are known to implement version negotiation incorrectly. For example, there are buggy TLS 1.0 servers that simply close the connection when the client offers a version newer than TLS 1.0. Also, it is known that some servers will refuse the connection if any TLS extensions are included in ClientHello. Interoperability with such buggy servers is a complex topic beyond the scope of this document, and may require multiple connection attempts by the client.

For a single connection, SSL/TLS contains the necessary protection against version rollback. Namely, the ClientHello message contains the client_version field, which advertises its highest supported version, and the full contents of the ClientHello message, including this field, are part of the input to the hash function used to compute the Finished messages at the end of the handshake. This makes sure that the server saw the "right value", i.e. the same one as the client.

The crucial point, though, is that this relies on the security of SSL 3.0, not TLS 1.2. This kind of protection against rollback works not because the new version of the protocol is "protected", but because the old version already includes the protection. It also requires that the old standard (SSL 3.0) still has a "robust enough" handshake: an attacker who performs a version rollback attack, pushing back client and server down to SSL 3.0, must have the ability to completely break SSL 3.0 right before the Finished messages; otherwise, these Finished messages will detect the rollback.

SSL 2.0 did not have such hash-based Finished messages (it had verification messages, but based on random challenges, not on the contents of previous handshake messages), it was possible for a MitM attacker to force a client and server to do SSL 2.0 instead of SSL 3.0 and they would not know it. SSL 2.0 is not "protected enough" against rollback, contrary to SSL 3.0, so the solution was to smuggle an equivalent of the client_version field in a place where cryptography would protect it (as specified in SSL 3.0, this was done in the PKCS#1 v1.5 "type 2" padding for RSA-encryption of the premaster secret).

Version rollback attacks are moot; or at least so it can be argued. Indeed, any version rollback attack can force client and server to use only versions and algorithms that they are willing to use. If SSL 3.0 was considered weak, then why would the client and server agree to use it ? If falling back to SSL 3.0 was considered a problem, then a client noticing a server which apparently cannot handle TLS 1.x for any value of x would simply refuse to connect at all. Conversely, if the client accepts to use SSL 3.0, then SSL 3.0 is fine.

This argument is of course a bit abrupt, but it highlights the fact that version selection is an opportunistic system meant to unlock non-essential functionalities, and should not be considered a security feature. If the client really wants to favour interoperability over security, as @Henrick explains, then there is no real way to prevent it.

For instance, suppose that TLS is expanded with an anti-rollback protection mechanism. This requires, as in the case of SSL 2, smuggling a true_client_version field somewhere in the SSL 3.0 handshake messages in a way which won't prevent interoperability with old, buggy servers (or old, buggy firewalls and intrusion detection systems). Extensions (at the end of the ClientHello) cannot be used, because such extensions are part of what makes old buggy servers fail. However, one could put things in the client_random value. That random has length 32 bytes; the first four bytes are the current time, so there are 28 actually random bytes. 16 random bytes are sufficient for "randomness"; this leaves us 12 bytes to play with. One could specify that the last 12 bytes of the client_random should contain a specific value, e.g. 6 successive copies of the actual most recent version supported by the client. A client unaware of this convention has only probability 2-80 to follow this pattern, and an old buggy server should not break on such a client_random.

Then a recent server, aware of the convention, would be able to see whether it is talking to a client which apparently requests SSL 3.0 or TLS 1.0, but claims in this surreptitious way that it can do TLS 1.2. The server would then be aware of some foul play. However, that could be the result of some misbehaving firewall, which, from a cryptographer's point of view, is an attacker, but not from a business point of view. Old, buggy systems are much more common than attacks. Even if the server decided to shut down the connection at that point, the client may still decide that, possibly, some old and buggy firewall blocks TLS 1.2 ClientHello, and then try again, mimicking a SSL 3.0 client -- including not encoding the version in the client_random, thereby deactivating the anti-rollback system we just defined. A Web browser who already tries multiple connections to deal with old buggy servers would probably keep on doing that.

To sum up, as long as the client really wants to connect, even if it implies falling back to SSL 3.0, and the server still accepts to talk to an SSL 3.0-only client (thus without any kind of anti-rollback system defined afterwards), then there is nothing that can be done on the server to prevent it. The client always has the possibility to perfectly mimic an old client, if that's what it takes to get through firewalls and anti-rollback systems and whatever. This is not specific to SSL.

To a large extent, the same applies to SSL 2.0. The anti-rollback system which was added in SSL 3.0 makes sense only as a transitioning mechanism. If SSL 2.0 is weak, then the security issue is not that an attacker could force client and server to fallback to SSL 2.0; the real issue is that client and server accept to use SSL 2.0 at all. The real protection against version rollback attacks is to reject weak versions altogether (as RFC 6176 suggests).

-
That's an interesting read, Thomas. I'm glad I'm currently mostly involved with interop of business machines instead of browser/server connections; just enabling one specific TLS protocol helps a lot :) –  Maarten Bodewes Sep 22 '13 at 14:14