CloudFlare makes extensive use of TLS connections throughout our service which makes staying on top of the latest news about security problems with TLS a priority. We use TLS both externally and internally and different uses of TLS have different constraints.
Broadly there are three ways we use TLS: to handle HTTPS connections from web browsers visiting web sites that use CloudFlare, to make HTTPS connections from our network of datacenters to our customers' web servers, and internally within our network.
This week, news of a new type of attack against the RC4 cipher used for some TLS connections has made us reevaluate (once again) all our use of TLS and specifically which ciphersuites we are using.
This blog post gives some background on TLS and ciphersuites, the most recent attack and how we are configuring our systems to keep our customers (and their customers) as safe as possible.
TLS and Ciphersuites
When two computers want to communicate securely using TLS, one of them (referred to as the client) connects to the other (the server) and they enter a negotiation about what encryption method to use. Central to that communication is an agreement between client and server on which ciphersuite will be used. The ciphersuite specifies precisely the type of encryption that will be used between client and server.
For example, when you visit a web site such as https://cloudflare.com/ using HTTPS a TLS connection is established between your web browser and the CloudFlare web server. Your web browser starts the TLS connection by telling the web server which ciphersuites it supports: it tells the web server which types of encryption it is able to use.
The list of available ciphersuites varies from browser to browser and from version to version. The University of Hannover has a little web site that will show you which ciphersuites your web browser supports. To use it just visit https://cc.dcsec.uni-hannover.de/.
For my browser, the latest version of Google Chrome, the list of suites is as follows. The order gives the web browser's preference for ciphersuites. For example, it would prefer to use
ECDHE-ECDSA-AES256-SHA
instead of
ECDHE-RSA-AES256-SHA.
ECDHE-ECDSA-AES256-SHA ECDHE-RSA-AES256-SHA DHE-RSA-CAMELLIA256-SHA DHE-DSS-CAMELLIA256-SHA DHE-RSA-AES256-SHADHE-DSS-AES256-SHA ECDH-RSA-AES256-SHAECDH-ECDSA-AES256-SHARSA-CAMELLIA256-SHA RSA-AES256-SHAECDHE-ECDSA-RC4128-SHA ECDHE-ECDSA-AES128-SHA ECDHE-RSA-RC4128-SHA ECDHE-RSA-AES128-SHA DHE-RSA-CAMELLIA128-SHA DHE-DSS-CAMELLIA128-SHA DHE-DSS-RC4128-SHA DHE-RSA-AES128-SHA DHE-DSS-AES128-SHA ECDH-RSA-RC4128-SHA ECDH-RSA-AES128-SHA ECDH-ECDSA-RC4128-SHA ECDH-ECDSA-AES128-SHA RSA-SEED-SHA RSA-CAMELLIA128-SHA RSA-RC4128-SHA RSA-RC4128-MD5 RSA-AES128-SHA ECDHE-ECDSA-3DES-EDE-SHA ECDHE-RSA-3DES-EDE-SHA DHE-RSA-3DES-EDE-SHA DHE-DSS-3DES-EDE-SHA ECDH-RSA-3DES-EDE-SHAECDH-ECDSA-3DES-EDE-SHA RSA-FIPS-3DES-EDE-SHA RSA-3DES-EDE-SHA
Each web server will have a similar list of ciphersuites and during the TLS handshake (at the start of a TLS connection) the client and server will agree on a ciphersuite that they both understand taking into account the order of preference of the client and server.
When I connect to https://cloudflare.com/ my browser and the CloudFlare web server agree to use ECDHE-RSA-RC4128-SHA. That cryptic string has a lot of information in it. It explains how the browser and server will exchange or agree onencryption keys and how the actual web browsing I do will be encrypted.
It breaks down as follows:
ECDHE means that the client and server will agree on encryption keys using Ephemeral Elliptic Curve Diffie-Hellman.
RSA means that the client will verify that the key is valid using the RSA algorithm to communications.
RC4128 means that the actual encryption of my web browsing session will be performed using the RC4 algorithm with a 128-bit key (that's the key that the client and server will have agreed using ECDHE-RSA).
And finally SHA means that the SHA algorithm will be used for securely hashing parts of the TLS messages.
CloudFlare's server configuration for TLS ciphersuites is set in nginx (which we use extensively) with the following configuration command:
ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-RC4-SHA: ECDHE-RSA-AES128-SHA:AES128-GCM-SHA256:RC4:HIGH: !MD5:!aNULL:!EDH:!CAMELLIA; ssl_prefer_server_ciphers on;
(Note that a previous version of this blog post had the wrong configuration caused by yours truly copy/pasting the wrong thing).
That results on the server offering the following ciphersuites (you can check this yourself using the SSL Labs Report):
ECDHE-RSA-AES128-GCM-SHA256 ECDHE-RSA-RC4128-SHA ECDHE-RSA-AES128-CBC-SHA RSA-AES128-GCM-SHA256 RSA-RC4128-SHA ECDHE-RSA-AES256-GCM-SHA384 ECDHE-RSA-AES256-CBC-SHA384 ECDHE-RSA-AES256-CBC-SHA RSA-AES256-GCM-SHA384 RSA-AES256-CBC-SHA256 RSA-AES256-CBC-SHA ECDHE-RSA-3DES-EDE-CBC-SHA RSA-3DES-EDE-CBC-SHA ECDHE-RSA-AES128-CBC-SHA256 RSA-AES128-CBC-SHA256 RSA-AES128-CBC-SHA
The CloudFlare server's preference is ECDHE-RSA-AES128-GCM SHA256 but unfortunately it is not widely supported. Yet. I'll come back to that ciphersuite later. So, my browser and the server agreed to use the server's second preference, ECDHE-RSA-RC4128-SHA.
Forward Secrecy
You'll notice that we've configured the CloudFlare server to prefer ciphers that use ECDHE. That's because, unlike the ciphers that start with RSA, they offer forward secrecy. To understand forward secrecy it's best to start by understanding systems that don't offer it, such as RSA.
When using RSA, the server's public key is used to encrypt a secret created by the client, the web browser. Because the server has the private key it can read the secret and both the client and server then know a shared secret that they can use for encryption. But the server's public RSA key is part of the server certificate and is typically very long lived. It's not uncommon for the same public key to be used for months or years (the current CloudFlare RSA key isn't set to expire until December 5, 2013). That creates a potential problem: if an SSL server's private key were to leak or be stolen all connections made in the past using that key would be vulnerable. It would be enough that someone had recorded your SSL connections: with the private key they could all be decrypted.
But forward secrecy with ECDHE means a fresh public key is created for every single connection. That means that an adversary would need to break the key for each connection individually to read the communication. And the keys are ephemeral: the server forgets them when connections are done. So there's nothing to leak.
So, we've prioritized those ciphers because they offer a higher level of long term security for people contacting CloudFlare sites.
I mentioned above that the ciphersuite that CloudFlare prefers is ECDHE-RSA-AES128-GCM-SHA256 and that ECDHE is preferred because it offer forward secrecy. The next part of the ciphersuite is RSA. In the ECDHE scheme that's just used to prove the identity of web server, and not to secure the connection, so the concerns above about leakage of the private key don't apply.
The next part is AES128-GCM. This is the cipher that will be used to encrypt the actual HTTP requests and responses encrypted in the TLS connection. This particular cipher is using AES with a 128 bit key in Galois/Counter Mode. Unfortunately, this very strong cipher is only part of TLSv1.2 which is not widely supported by web browsers. CloudFlare has it configured ready for the day when it is supported because it is very secure.
Double Trouble
Since TLSv1.2 isn't widely supported, the two popular ciphers used to secure the data sent across a TLS connection are RC4 and AES (in CBC mode). Both have flaws and both have attacks that could be used against them. Very recently a new attack against RC4 was announced that could allow an attacker to recover parts of the original HTTP message (such as a cookie value) when RC4 is used.
The CBC mode ciphers have attacks called Lucky-13 which we've discussed before and BEAST which we've also talked about.
Because BEAST and Lucky-13 both attack CBC-based ciphers, CloudFlare decided in the past to prioritize the use of the other cipher:
RC4. Unfortunately, the latest attack goes after RC4. So now both the popular ciphers have published flaws. The sooner browser vendors move to TLSv1.2 and away from RC4 and AES in CBC mode the better.
RC4 Keystream Biases
The new RC4 attack is based on biases in the RC4 keystream. To understand how the attack works it's necessary to understand a little of how RC4 works.
RC4 operates by generating a pseudorandom stream of bytes of data called the keystream. These bytes are XORed with the information to be encrypted and the result is transmitted. For example, suppose that the word SECRET is to be sent using RC4.
In ASCII, SECRET is the following six hexadecimal numbers:
S E C R E T 83 69 67 82 69 84
Suppose that RC4 generates the following six bytes in the keystream:
85 B8 D6 6B C7 51
To encrypt SECRET the keystream is XORed with the word SECRET byte by byte and the result, 06 D1 B1 E9 AE D5, is transmitted.
S E C R E T
Message: 83 69 67 82 69 84 Keystream: 85 B8 D6 6B C7 51 XOR ----------------- Ciphertext: 06 D1 B1 E9 AE D5
(This XOR technique dates all the way back to 1919 with the Vernam Cipher; read the Wikipedia article for a basic introduction to the use of XOR in ciphers. RC4 itself, of course, is much more recent.)
The exact pseudorandom sequence that RC4 generates depends on the key used. As long as both client and server have the same key they can generate the same keystream and perform the same set of XOR operations to encrypt and decrypt data. That's because XOR is its own inverse: if you do Z = X XOR Y and then do Z XOR Y you get back to X.
So, when 06 D1 B1 E9 AE D5 is received on the other side it performs the same XOR operation with the same keystream sequence to recover the original message.
Ciphertext: 06 D1 B1 E9 AE D5 Keystream: 85 B8 D6 6B C7 51 XOR ----------------- Message: 83 69 67 82 69 84 S E C R E T
But it's vital that the keystream be random so that an eavesdropper can't obtain any useful information from the ciphertext. If the random stream contained biases (such as some numbers that came up more often than others) it would be possible to use probability to predict what the original, unencrypted message was.
That's what the latest RC4 attack shows. Specifically, there are biases in the first 256 bytes of keystream generated by RC4. Those first bytes are likely to be used to encrypt the start of an HTTP request and may include sensitive information such as a cookie used for logging into a web site.
The attack works by causing the same request to occur over and over again (for example, using a piece of JavaScript to contact the same web site repeatedly). On each connection the same request (with the same cookie) will be encrypted with RC4. A different key is used each time which results in a different keystream, but over many encryptions any biases in the keystream will show up as certain numbers appearing in the ciphertext more or less often than others (because some numbers appeared more often than others in the keystream).
The numbers that make up the RC4 keystream should be totally random. So if the same message, such as the word SECRET above, is encrypted over and over again with RC4 the resulting ciphertexts should be totally random: the probability of each number between 00 and FF appearing should be the same. If you encrypted SECRET over and over again with RC4 and counted the number of occurrences of 00 to FF in the ciphertext they should be roughly equal. Just as if you roll a fair die over and over again and count how many times the numbers 1 to 6 appear they should be equal.
Unfortunately, the researchers have discovered that the first 256 bytes of the keystream are not completely random and over time a pattern emerges.
For example, here's their chart showing the probability of each number appearing as the first number produced in the RC4 keystream. This should be completely flat with each number being equally probable. It's not. That means that if the same message were encrypted over and over again it would be possible to determine (with a certain probability) what the original first character was.
With many repeated tests, just as rolling a loaded die many times would show which numbers come up most often, the attack can see which ciphertext numbers come up most frequently and match that pattern to the pattern in the keystream. From that a simple XOR can reveal the original message.
And the same authors describe another attack based on biases in adjacent numbers in the keystream that works at any point, not just in the first 256 bytes.
So both of the widely supported ciphers have faults. These faults are exploitable by attackers under the right conditions; they are not theoretical attacks, but they are hard to pull off. Nevertheless, CloudFlare will be happy when we can move away from RC4 and CBC-based ciphers and put Lucky-13, BEAST and others behind us.
Protecting Internal Systems
While CloudFlare has to wait for browser makers to implement the latest and safest cryptography, we don't have to wait for any of our internal systems.
CloudFlare uses TLS internally extensively (and between CloudFlare software components like Railgun) and has recently done an audit of all uses of TLS to ensure that the best ciphers are in use. And so for situations where CloudFlare controls both the client and server we are deprecating use of TLSv1.1 and switching to TLSv1.2 with ECDHE-RSA-AES128-GCM-SHA256 as the current cipher of choice.
As the world of cryptography and TLS changes CloudFlare will keep updating its systems to keep them at the forefront of the available research.