Adam Innes · Blog

POODLE Is Your Cue to Turn Off SSLv3

· 8 min · security, tls, nginx, apache

Last Tuesday, October 14, Google published a flaw in SSL 3.0 with a name that’s hard to take seriously and a mechanism that deserves to be. POODLE stands for Padding Oracle On Downgraded Legacy Encryption, and it’s tracked as CVE-2014-3566. The short version for anyone running a web server is that if your server still accepts SSL 3.0, a well placed attacker can talk visitors’ browsers down to it and start pulling secrets like session cookies out of their HTTPS traffic, even if those browsers and your server both speak TLS 1.2 perfectly well.

The good news is that the attack only works if your server agrees to speak SSL 3.0, and that part lives in your config file.

What the attack actually needs

The details are in the Google security advisory by Bodo Möller, Thai Duong and Krzysztof Kotowicz. Stripped down, POODLE needs three things to line up.

First, the attacker has to be a man in the middle, able to see and modify traffic between the browser and your server. The US-CERT alert TA14-290A, released October 17, points out that this is a whole separate attack in itself, and that places already prone to it, like public WiFi, make it easier. The attacker also needs a way to make the victim’s browser send lots of requests to your site, which the paper describes doing with JavaScript running on a page the attacker controls or can inject into.

Second, the connection has to be running SSL 3.0, which means your server has to accept it. A browser and a server that both speak TLS won’t normally settle on SSL 3.0, so the attacker has to force the downgrade, which is where the name comes from, and your server has to go along with it.

Third, the session has to be using a CBC mode cipher, and that’s where SSL 3.0 itself is broken. When SSL 3.0 encrypts a record with a block cipher, it appends a MAC to the data and then pads the whole thing out to a full block. The padding isn’t covered by the MAC, and apart from the final byte, which says how long the padding is, its contents can be anything. So the server has no way to check most of what it decrypts in that last block. The attack works best when the padding fills an entire block, and since the attacker controls the request path and body, it can size the request so that happens. When it then swaps that last encrypted block for an earlier one, the record usually gets rejected, but when the final byte happens to decrypt to the right value, it’s accepted. The paper puts that at about once in 256 tries, and each acceptance tells the attacker one byte of plaintext. Line the cookie up at the right position over and over and it comes out one byte at a time.

Diagram of an SSL 3.0 CBC record showing that the padding sits outside the MAC

You might wonder whether you could keep SSL 3.0 and just avoid CBC. The only other option SSL 3.0 has is RC4, and the paper notes that RC4’s known biases leak information about secrets sent repeatedly over many connections. Its conclusion is blunt: there are no secure SSL 3.0 cipher suites left.

Why browsers fall back to SSL 3.0 at all

TLS already has proper version negotiation built into the handshake. The client says the highest version it supports, and the server answers with the highest version they share. On paper, a modern browser and a modern server should never land on SSL 3.0.

The problem is that some servers have interoperability bugs, so a handshake offering a newer version can fail where an older one would work. To keep those sites working, browsers added what the paper calls a downgrade dance. If a handshake offering TLS 1.2 fails, the browser tries again with an older version, then an older one, all the way down to SSL 3.0. Google’s own announcement post describes it as browsers retrying failed connections to work around bugs in HTTPS servers.

The dance doesn’t care why a handshake failed, though. As the paper points out, a network glitch or an attacker interfering with the connection triggers the retry just as well as a buggy server does. So the attacker just kills every attempt until the browser offers SSL 3.0, then lets that one through. If your server still accepts SSL 3.0, it agrees.

Diagram of an attacker killing TLS handshakes until the browser retries with SSL 3.0

The real fix is turning SSL 3.0 off

The advisory is clear that disabling SSL 3.0 on either the client or the server completely avoids the attack, because there’s never an SSL 3.0 connection to break. You can’t make browsers update, but you can make sure your server refuses the downgraded handshake. US-CERT says the same thing, calling disabling SSL 3.0 the most viable solution currently available.

On nginx, this is the ssl_protocols directive. In nginx releases shipping as I write this, the default is SSLv3 TLSv1 TLSv1.1 TLSv1.2, so if you never set it yourself, SSL 3.0 is on. The nginx documentation shows the directive works in the http or server context, and the fix is to list only the TLS versions. The TLSv1.1 and TLSv1.2 parameters need nginx 1.1.13 or 1.0.12 and later, plus OpenSSL 1.0.1 or newer.

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

If you set it in http, it’s worth grepping your config to make sure no server block sets its own ssl_protocols with SSLv3 still in it.

On Apache httpd, the directive is SSLProtocol, and its default is all. In the 2.4 documentation, all means +SSLv3 +TLSv1, plus TLS 1.1 and 1.2 with OpenSSL 1.0.1 or later. So again, SSL 3.0 is on unless you’ve said otherwise. Subtract it:

SSLProtocol all -SSLv3

Apache 2.2 is slightly different, because its All still includes SSLv2 as well, so you take both out:

SSLProtocol All -SSLv2 -SSLv3

SSLProtocol is allowed in both server config and virtual host context, so check each HTTPS virtual host for its own line. Then reload the server so the change actually takes effect. If you’re on Windows, Microsoft’s Security Advisory 3009008 was revised on October 15 with a registry setting that disables SSL 3.0 for all server software on the machine, IIS included.

TLS_FALLBACK_SCSV, the fix for the dance itself

Disabling SSL 3.0 stops POODLE, but the downgrade dance is still a problem in general, since the same trick can push a connection from TLS 1.2 down to TLS 1.1 or 1.0. Google’s post actually recommends something else first, because it says disabling SSL 3.0 still presents significant compatibility problems. That recommendation is a mechanism called TLS_FALLBACK_SCSV, described in the IETF draft draft-ietf-tls-downgrade-scsv-00 by Möller and Adam Langley.

The idea is small and clever. When a client retries with a lower version than it really supports, it includes a special value, 0x56, 0x00, in its list of cipher suites. That value isn’t a real cipher. It’s a flag that tells the server, in effect, that the client is only offering this version because a better attempt failed. A server that understands the flag compares the client’s offered version with the highest version the server supports. If the server could have used a higher version, the fallback wasn’t needed, and the server kills the handshake with a new fatal alert called inappropriate_fallback. Because it travels as a cipher suite value, the signal is backwards compatible, so the fallback still works for genuinely old servers, and SSL 3.0 only gets used when a legacy implementation is really involved.

Diagram of a server rejecting an SSL 3.0 fallback that carries TLS_FALLBACK_SCSV

It only helps when both sides support it. Google says Chrome and Google’s servers have supported TLS_FALLBACK_SCSV since February, and that Chrome is starting to test changes that disable the fallback to SSL 3.0. The Mozilla Security Blog says Firefox 34, due November 25, will disable SSL 3.0 by default, and Firefox 35 will support the SCSV.

On the server side, the OpenSSL security advisory from October 15 added TLS_FALLBACK_SCSV support in three releases: 1.0.1j for the 1.0.1 branch, 1.0.0o for 1.0.0, and 0.9.8zc for 0.9.8. The same releases fix a session ticket memory leak and a bug where building OpenSSL with no-ssl3 didn’t fully remove SSL 3.0, and 1.0.1j also fixes a second leak in the DTLS SRTP code, so this is an update you want anyway. In 1.0.1j the server side check is done inside the library when it parses the client’s hello, so there’s nothing to configure in nginx or Apache. What you do need is for the running server processes to actually be using the new library, which usually means restarting them after the package update, and rebuilding if your server has OpenSSL compiled in statically.

What turning off SSL 3.0 breaks

Clients that can’t speak anything newer than SSL 3.0 won’t be able to connect. According to Mozilla, the only remaining browser that doesn’t support TLS 1.0 is Internet Explorer 6, and they acknowledge that many sites still get IE6 traffic and may not be able to switch SSL 3.0 off right away. Mozilla also says SSL 3.0 accounts for only about 0.3% of Firefox HTTPS connections, which is tiny as a percentage but still millions of transactions a day.

Before flipping the switch, look at your own traffic. If you have IE6 visitors you can’t live without, TLS_FALLBACK_SCSV on an updated OpenSSL at least stops browsers that send the flag (Chrome today, Firefox from version 35) from being dragged down, while SSL 3.0 stays available for the clients that truly need it. Just remember that those IE6 users are still exposed. Also think beyond browsers. US-CERT notes that POODLE applies to any software that supports SSL 3.0 with CBC mode ciphers, not just browsers and web servers, and my guess is that the clients most likely to break quietly are old API integrations and scripts running on ancient TLS libraries, because nobody is watching them.

Checking that it worked

The openssl command line tool has an s_client command that is perfect for this. Run it from your machine against your own server, forcing SSL 3.0:

openssl s_client -connect example.com:443 -ssl3

If SSL 3.0 is off, expect a handshake failure, with no peer certificate available and Cipher is (NONE) in the output. s_client still prints a session block either way, so don’t read anything into that. If you see your real certificate chain and an actual cipher name, SSL 3.0 is still enabled somewhere. One gotcha is that if your local OpenSSL was built without SSL 3.0 support, the -ssl3 flag won’t exist, and you’ll get an unknown option message that tells you nothing about your server.

Once you have OpenSSL 1.0.1j on the client side too, s_client gains a -fallback_scsv flag, and you can test the downgrade protection directly. If your server runs an updated OpenSSL and supports something newer than TLS 1.0, this should be rejected:

openssl s_client -connect example.com:443 -tls1 -fallback_scsv

Run both checks against every hostname and port you serve TLS on, not just the main site, because it’s easy to fix one virtual host and forget the others.

The takeaway

SSL 3.0 is nearly 18 years old, and POODLE makes the case that it can’t be patched into safety. The attacker has to control the network and trick the browser, and neither of those is up to you. What is up to you is whether your server says yes when the downgraded handshake arrives. Take SSL 3.0 out of ssl_protocols or SSLProtocol, update OpenSSL so your server understands TLS_FALLBACK_SCSV, and run s_client against every endpoint to prove it.

← all posts