Hardening SSL
By Roman Pertl
Update: 2014/01/17: Again a few weeks have past without finishing the article. So I’m going to publish it anyway even it it is unfinished work yet. I also disabled OCSP Stapling again. I’m using StartSSL and I’ve had some issues with their OCSP website. Also the nginx implementation is still not “mature” (see: http://nginx.org/patches/attic/ocsp-stapling/README.txt). There are some limitations for less used sites e.g. the OCSP stapling information is stored for each worker. I was getting the “OCSP stapling information outdated” site in my browser often when open my secure site.
Update: 2013/12/21: During writing this post and with the discussion with my colleagues in the last weeks (yeah, it’s already that long since I started writing on this article), the following site came to our attention: Applied Crypto Hardening (https://bettercrypto.org/). This whitepaper is still a draft but already contains a lot more information than this blog post could ever provide 🙂
It’s the year 2013. An important year concerning security/privacy in the Internet. Because of recent articles in the press I wanted to do a check about the strength of the encryption – both on my private server and also on the websites we are maintaining at the company I work for. And it was a good thing I did this because it turned out that we didn’t update the SSL for year. Especially the configuration on nginx wasn’t “uptodate”. Apparently when we setup the first nginx server we didn’t pay so much attention to that fact and didn’t use far from optiomal settings. Although the settings on Apache were not that suboptimal, they were still 2 or 3 years old and have been copied over and over again without paying attention to them. Anyway after reading some articles (most of the important ones are listed as references at the end of the port).
Forward Secrecy
Forward Secrecy – also called Perfect Forward Secrecy is a small, but important change in the way the key for the symmetric encryption is exchanged between client and server. In traditional SSL the client sends the session’s symmetric key encrypted with the public key of the server. Someone in the possession of the private key of the server can encrypt the whole communication (this also works for communications happened in the past). Forward Secrecy uses the mathematical principle of Diffie-Hellman to establish a session key by exchanging several messages between client and server and computing the session key out of this messages. Thus the session is key is never sent during the whole process and after the sessions ends and client and server delete the session key the session cannot be decrypted anymore. This also has some drawbacks e.g. higher CPU utilization and slower responses, but security comes with a prices – always 😉 See [1] and [2]
OCSP Stapling
If you are on a recent version of apache or nginx, you can also enable OCSP Stapling. This enhances the former CRL (Certificate Revocation List) und OCSP (Online Certificate Status Protocol). Both of these checks are implemented by the client and the clients needs to verify the certificate at the CA (Certification Authority). With OCSP Stapling the server itself contacts the CA and receive the verification (which is valid for some hours and thus many requests) and sends it back to the client (see [3]).
Strict Transport Security (STS)
The Strict Transport Security (STS) Headers forces a client to only use HTTPS with a site and can be sent on a HTTP request and is cached for a certain amount amount of time, so there are no unencrpyted request after the first initial request.
Removing Compatibility
The most current SSL standard is TLS 1.2. Only the most recent version of servers and browsers are already supporting this standard. On the other hand, SSLv2 is only used by browsers several years old and should be removed in any case. If you need to support WindowsXP and IE, you need to stick to SSLv3, otherwise you should only support TLSv1+. So especially for internal sites where you do not expect such old clients, you should be safely able to remove SSLv3.
Getting a new Certificate
If you are thinking about getting a new certificate you should make sure that your private key uses 4096 bits. Otherwise you will not receive 100 percent with the SSLlabs tests. But still the usual 80% should be pretty fine.
Deciding about the used Cipers
This is a bit complicated than to choose the available protocols. Because you want to force the client to use the best available protocol and you want to support as many clients as possible.
This is basically the same for nginx and Apache: Both use the underlying openssl for the encryption and in both configurations you set an openssl cipher string, which is validated and used by openssl.
After reading a lot of blog entries I decided to go with this ciphers suite:
EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH+aRSA+RC4 EECDH EDH+aRSA RC4 !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS !RC4
And if this is a site which should support WindowsXP + IE you can use this one (which includes RC4):
If you would like to get 100% on the SSLlabs tests you need to exclude some ciphers with “!CAMELLIA128:!ECDSA:AES256-SHA !SEED” (append at the end of list, but before the last RC4).
You can test the cipher with:
shell$ openssl ciphers -v
nginx
ssl_session_cache shared:SSL:50m;
ssl_session_timeout 5m;
keepalive_timeout 120; # 120 second keep alive
Some generic settings for the HTTP keepalive and the SSL session cache.
ssl_prefer_server_ciphers on;
ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers $CIPHERS
# Enable this if your want HSTS (recommended, but be careful)
add_header Strict-Transport-Security max-age=15768000 ; includeSubdomains
The first parameters forces the client to use the servers choise of ciphers, the second parameter defines the used protocols (see above), the third options sets the used ciphers (see above).
SSL Compression should be disabled by default with a recent version of nginx and openssl (for details see [5])
OCSP Stapling
If you are using version 1.4, you can enable OCSP Stapling with the following directives (see [4]):
## OCSP Stapling ---
## fetch OCSP records from URL in ssl_certificate and cache them
ssl_stapling on;
## the server itself should valid the OCSP before sending to the client
ssl_stapling_verify on;
## verify chain of trust of OCSP response using Root CA and Intermediate certs
ssl_trusted_certificate /path/to/root_CA_cert_plus_intermediates;
## you need to set a rsolver to resolve the OCSP URL
resolver 8.8.8.8;
apache
SSLHonorCipherOrder On
SSLProtocol ALL -SSLv2
SSLCipherSuite $CIPHER
Does basically the same thing as on apache: First force the client to use the best cipher available, define which protocols to use (see above) and at last define which ciphers to use (see above).
You might want to try to disable SSL Compression with (again this depends on the apache version, seee [4] for details):
SSLCompression Off
Verifying your changes
One of the best online tests should be the this one: https://www.ssllabs.com/ssltest/
openssl s_client -connect imap.1und1.de:993
openssl s_client -cipher 'ECDH:DH' -connect login.live.com:443
openssl ciphers -V
Conclusion
I strongly recommend checking the SSL settings for your site (e.g. via the ssltest website) and changing the configuration accordingly! The final result should look something like this:
References
- Heise Forward Secrecy (in German) http://www.heise.de/security/artikel/Forward-Secrecy-testen-und-einrichten-1932806.html
- Hiese Forward Secrecy (in German) http://www.heise.de/security/artikel/Zukunftssicher-Verschluesseln-mit-Perfect-Forward-Secrecy-1923800.html
- OCSP Stapling Article at Golem (in German): http://www.golem.de/news/firefox-mitgelieferte-gueltigkeitspruefung-fuer-zertifikate-1307-100700.html
- SSLtest by Qualys: https://www.ssllabs.com/ssltest/
- Blog Entry by Hynek Schlawack https://hynek.me/articles/hardening-your-web-servers-ssl-ciphers/
- OCSP Stapling Blog Article: https://jve.linuxwall.info/blog/index.php?post/2013/10/12/A-grade-SSL/TLS-with-Nginx-and-StartSSL
- Serverdensity Blog Entry about securing Webapps: https://blog.serverdensity.com/how-to-secure-your-webapp/
- Lognormal Blog Entry about nginx+ssl: http://www.lognormal.com/blog/2013/06/22/setting-up-ssl-on-nginx/
- Blog Entry by Julien Vehent: https://jve.linuxwall.info/blog/index.php?post/2013/10/12/A-grade-SSL/TLS-with-Nginx-and-StartSSL
- Blog Entry by Ivan Ristić http://blog.ivanristic.com/2013/08/configuring-apache-nginx-and-openssl-for-forward-secrecy.html
- Blog Entry by Mike Kuketz http://www.kuketz-blog.de/nsa-abhoersichere-ssl-verschluesselung-fuer-apache-und-nginx/
- SSL Rating Guide https://www.ssllabs.com/downloads/SSL_Server_Rating_Guide_2009d.pdf