Last month a serious SSL/TLS vulnerability named “DROWN” – “Decrypting RSA with Obsolete and Weakened eNcryption” – broke the surface. In this article I will explore the mechanics of the attack and why it works. I wanted to have a closer look at DROWN because it is a beautiful hack and a prime example of how the mere existence of deliberately weakened ciphers hurts us still today, years after we’ve deprecated them. But first…
Some practical information
DROWN is a padding oracle attack that enables an attacker to obtain the session keys for, and hence decrypt, a captured TLS session by repeatedly probing the server using the SSLv2 protocol. Use of SSLv2 has long been deprecated by browsers and before DROWN it was believed that supporting SSLv2 was not a big issue since clients would never use it. However, DROWN shows us how merely supporting an outdated protocol like SSLv2 can pose a real threat to more modern protocols.
Is your server vulnerable?
A test for vulnerability, together with the essential practical information, has been published on a dedicated website:
A server is vulnerable if it supports SSLv2 with export-grade ciphers, or it shares its certificate with a server that does. At the time of disclosure (March 1st), that was 33% of HTTPS servers on the web.
The efforts of the attacker (feasibility)
The attacker has to passively eavesdrop about 1000 TLS connections to a vulnerable server in order to successfully decrypt a victim’s session. The attack requires the attacker to expend, for example, $440 on Amazon EC2 cloud computing platform during 8h of computation, or, in the case of OpenSSL that predates march 4, 2015, less than a minute on a single PC.
Dissecting the vulnerability
Now let’s have a look at what the vulnerability is. I won’t get into the underlying mathematics because they are, of course, quite involved. Here we go…
Decrypting a secure connection
In a secure connection the client and server negotiate secret session keys in order to be able to encrypt all the traffic of their session. This negotiation is called a “handshake”.
The secrecy of these session keys relies on the secrecy of a so-called “pre-master secret” (PMS) which is used by both server and client to derive the same session keys. During the handshake the client generates the PMS and sends it to the server in a message called “ClientKeyExchange” which is encrypted using the server’s public key.
So the problem for an eavesdropping attacker is to get the plain-text PMS from the encrypted “ClientKeyExchange” message.
DROWN exploits the fact that SSLv2, because of support for weak 40-bit export-grade ciphers, is vulnerable to a kind of padding oracle attack that was first introduced by David Bleichenbacher in 1998. The DROWN researchers have shown us that this oracle can also be used to decrypt a modern TLS connection if the same certificate, hence the same RSA key pair, is used for serving both SSLv2 and TLS.
Bleichenbacher’s attack, and therefore also DROWN, applies to a particular padding scheme called “PKCS#1 v1.5” which is standard for RSA-based handshakes for both SSL and TLS. A padding scheme is used to expand a piece of plain-text to make it conform to the block size of a particular cipher algorithm.
Bleichenbacher showed how an attacker can deduce the plain-text contents of an encrypted message if the server discloses whether or not any submitted cipher-text is decrypted by the server into a correctly padded message according to the PKCS#1 v1.5 standard. Using a succession of chosen cipher-texts which are related to the target cipher-text, the attacker can then successively narrow the interval of possible values for the target plain-text. The submitted cipher-texts are successively refined based on the responses from the server and this is repeated until the interval of possible values for the target plain-text has been reduced to contain only the target plain-text itself. Bleichenbacher showed how this attack could be used on contemporary SSL handshakes to obtain the session keys of a recorded session.
The countermeasure for Bleichenbacher’s attack in SSL/TLS implementations is to protect the handshake by not letting the server disclose whether or not the “ClientKeyExchange” message contains a correctly padded PMS. Instead, if the server finds a wrongly padded PMS when decrypting the “ClientKeyExchange” message, then the server will randomly make up its own PMS and go ahead with the protocol. The protocol will then fail when the client and server exchange “finished” messages to conclude the handshake. The “finished” messages are encrypted using the derived session keys and if the server generated its own PMS, instead of getting it from the client, then the server’s derived session keys will not match whatever keys the client has come up with. The communication will then fail without having told the client whether or not the PMS was correctly padded and Bleichenbacher’s attack is therefore prevented.
With this countermeasure in mind we now note that if an attacker would send the same cipher-text twice then one of two things will happen: Either the cipher-text can be decrypted by the server into a correctly padded PMS message and the server will calculate session keys from the received PMS, or: The decrypted PMS will not be correctly padded and the server will randomly generate a PMS on its own. Having submitted the same cipher-text twice the first case will result in the server using same PMS twice to derive the session keys. The second case will result in two different randomly selected PMSs. So if there is a way for the attacker to tell if the server has used the same PMS twice when deriving the session keys then Bleichenbacher’s attack is re-enabled.
This is where the insufficiency of SSLv2 comes into play.
How SSLv2 breaks everything
SSLv2 has many flaws. Particularly two of them allow the attacker to learn whether or not the server has used the same PMS* for two handshakes.
(* In SSLv2 there actually is no “PMS”, instead there is a “Master Key”, also chosen by the client. But that’s beside the point and I’m going to keep referring to it as “PMS” for simplicity.)
Flaw 1: In the SSLv2 protocol (or at least all of its implementations) the server eagerly responds with a “ServerVerify” message immediately upon receiving the PMS, before the client has demonstrated knowledge of the session keys. The “ServerVerify” message is simply a random number, chosen by the client in the first stage of the handshake, encrypted using the server’s derived session key. The purpose of this message is to demonstrate to the client that the server knows its public key and has successfully derived the session keys.
Flaw 2: SSLv2 allows export-grade 40-bit encryption whose 2^40 key space can feasibly be searched by brute-force.
When exploiting these flaws the attacker will send its candidate cipher-text to the server and receive the “ServerVerify” message. The attacker will then perform a brute-force search over all 2^40 possibilities for the export-grade PMS to find the PMS that derives a server session key that successfully decrypts the “ServerVerify” message. The attacker will know when a brute-force attempt is successful because the message will then decrypt into the random number he has previously chosen.
Having found the PMS of the first message the attacker then submits the same candidate cipher-text again and receives the “ServerVerify” message. He now uses the PMS found from the first message to derive the server session key for this second session. If this server session key successfully decrypts the “ServerVerify” message then the attacker knows that the server has arrived at the same PMS twice, turning the server into a Bleichenbacher oracle.
This is DROWN: Bleichenbacher’s attack on RSA resurrected because of the weakness of SSLv2.
TLS is not SSL but…
There is one complication that an attacker must overcome in order to exploit DROWN to obtain the plain-text PMS from a victim’s TLS session: A “ClientKeyExchange” message for the TLS protocol does not necessarily conform to a 5-byte (40-bit) export-grade plain-text padded according to PKCS#1 v1.5. In fact, the chances that it does are pretty slim. However, it turns out that the attacker can apply cleverly chosen multiplication factors in order to greatly improve the chances of a target cipher-text being PKCS#1 v1.5 export-grade compliant. The attacker can expect success for about 1 in 1000 eavesdropped TLS connections.
Also the attack yields only a few plain-text bytes at a time because of the tiny key/PMS of the export-grade cipher. However this is a minor obstacle because the attacker can “rotate” the plain-text part exposed by the oracle to successively work out the full TLS PMS of the victim’s session. The underlying mathematics are quite involved and I refer the reader to the original paper for studying the details.
All-in-all, an attacker can expect to decrypt about 1 in 1000 recorded TLS sessions at the cost of $440 on Amazon EC2. Brute-forcing the “ServerVerify” message accounts for the larger part of the computational cost of performing the attack.
Special DROWN turns bad into worse!
This article has studied the general case. I would now like to turn your attention to “special DROWN”. When discovering DROWN the researches also discovered a bug in OpenSSL that was fixed by coincidence on March 4, 2015. This bug has been designated CVE-2016-0703 and the researchers were able to exploit it for DROWN to cut the number of required oracle connections by 50% and reduce the computational effort to perform in less than a minute on a single PC.
So, vulnerable OpenSSL installations that predate march 4 2015 cost essentially nothing to attack. The general DROWN attack has a significant price tag attached to it but one can expect it to be well within the business margin of a high-value target.
In conclusion, DROWN is a serious threat.