SSL/TLS ciphers


The problem at hand

You have a website and you want to encrypt the traffic going in and out of your webserver. Since you heard about the attacks currently known at SSL and TLS, you want to configure your server to not be vulnerable to any. In a perfect world (or if you control your clients) all you have to do is allow TLS 1.2 and AES-GCM with elliptic-curve Diffie-Hellman key exchange only (AESGCM+ECDH when using openssl) and you're set. This combination is secure, fast, offers perfect forward secrecy and at the time of writing there are no known attacks that make it crackable in a reasonable time. So what's the problem? With a public website you don't control the web browser the visitor uses. If he or she is using IE on Windows XP or Android 2.x the browser doesn't support TLS 1.2 or AES-GCM and the visitor can't access the website. How do you keep your website secure yet reasonably accessible?

Known attacks on SSL and TLS

First, SSL 2.0 is insecure (it's even disabled by default in IE7) so we'll not be using it. Version roll back attacks allow a man in the middle to change the response from the client to force a lower grade (read the lowest grade possible) cipher suite. The BEAST attack exploits a weakness in CBC ciphers in TLS 1.0. But fixes all major browsers have been released for quite some time, so we're going to assume that the client is secure and CBC ciphers are safe to use (reasonable assumption, but still an assumption). CRIME and BREACH exploit a weakness in compression and RC4 is considered to be weak although not broken like DES or MD5.

IE in Windows XP

All version of IE that are available on Windows XP offer RC4 and 3DES as the best ciphers available. Unfortunately Chrome uses the Windows scrypt library so it has the same limitation. For a user this means that if you're on Windows XP you should be using an up-to-date version of Firefox to have the best experience until you can move from Windows XP (or Windows in general). For the website manager it leaves you with 2 options, either add support for either 3DES or RC4 ciphers with SHA1 hashes (for openssl, add RC4-SHA or 3DES-SHA at the end of the cipher list) or ask users to use Firefox if they're still on XP. I chose the latter rather then the former, but I have that luxury.

What are we left with?

Since modern browser browsers that support SSL 3.0 support TLS 1.0, we'll be using TLS 1.0 or newer. Any AES cipher (AES-GCM preferred) with ECDH key exchange (preferred) or DH key exchange and SHA2 (preferred) or SHA1 hashes and disable compression. On my server (OpenBSD firewall/ load-balancer/ SSL terminator and reverse-proxy) with the included OpenSSL and Nginx the configuration is as followed

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers !kRSA:!3DES:!RC4:!DES:!MD5:!aNULL:!NULL:AESGCM+ECDH:AES256+ECDH:AES128:+SHA1;
ssl_prefer_server_ciphers on;

Take note that I first disable what I don't want, then allow what I do want in the order I prefer. I've also disabled DH key exchange with AES-GCM since all browsers that support AES-GCM support ECDH so I've opted for that (the reasoning being that ECDH is faster than DH so it's preferable).

Final words

This is not enough to call your site secure. I haven't mentioned secure cookies, HSTS, input sanitation, cross-site scripting, OCSP, certificate strength, implementation vulnerabilities (such as OpenSSL's heartbleed) or any of the other security considerations. For testing purposes I used sslscan and Calomel's SSL validation add-on for Firefox. You can also SSLLabs' SSL test.