ssllabs / ssllabs-scan

A command-line reference-implementation client for SSL Labs APIs, designed for automated and/or bulk testing.
https://www.ssllabs.com/projects/ssllabs-apis/
Apache License 2.0
1.69k stars 239 forks source link

TLS 1.3 Cipher Strength 90%? #636

Open shoujii opened 6 years ago

shoujii commented 6 years ago

Hey there, I tested my site -> nginx 1.15.1 using Openssl 1.1.1 pre release 8 on

https://dev.ssllabs.com/

with the following cipher list: TLS13-CHACHA20-POLY1305-SHA256:TLS13-AES-256-GCM-SHA384:TLS13-AES-128-GCM-SHA256

and I only got 90% Cipher Strength.

Am I doing something wrong?

https://www.openssl.org/blog/blog/2017/05/04/tlsv1.3/

There are only 5 TLS 1.3 Ciphers supported by openssl yet.

shibumi commented 5 years ago

did anybody found a solution for this? Right now I have a 100/100/100/100 Rating but with disabled TLSv1.3.. this is kind of stupid.

ArchangeGabriel commented 5 years ago

@shibumi Either patch nginx or recompile your OpenSSL. Or accept 128bit AES with TLS1.3 and don’t think too much about scoring 100%. Especially since 100% does not mean a lot, they are a lot of factors to work about to get good security. FWIW, you could score 100% but have the private key available publicly on GitHub… For instance, what elliptic curves are enabled on your setup?

mddvul22 commented 4 years ago

Dear all, we at SSL Labs are working on grading related changes at the moment. This would include changes related to TLS 1.3 protocol. Until then the effect on the score due to TLS_AES_128_GCM_SHA256 cipher suite would continue to exists, along with the alert error message on servers that do not support this mandatory cipher suite as per RFC-8446.

Any update on this? It has been 9 months since this post that grading related changes were coming. Thanks!

x-rated commented 4 years ago

Nobody cares, well done, SSL Labs...

naumanshah03 commented 4 years ago

@x-rated Apologize for the delay and thank you for your patience.

We are listening to all the suggestions given by the community users.

We have some other things lined up and at the same time, we need to make sure that everything is fine when it comes to grade in SSL Labs as it is a crucial part of it and users are affected because of it.

You can expect it soon.

ghost commented 4 years ago

Can you at least do a new grade for the people who have 100/100/100/90, because some website have the same result, when the have 100/100/90/90 and some orange warning (weak cipher, caa not found etc), (for exemple a+ but in orange (because of the warning) in the result, it des'nt change anyting to the calc but only change the color.

melroy89 commented 4 years ago

Hopefully Nginx will solve this strange SSL cipher issue with TLS v1.3.. anytime soon.

shibumi commented 4 years ago

@danger89 I just use caddy v2 now, there it's solved. TLS 1.3 support with good cipher strength

wibimaster commented 4 years ago

You can with nginx too ; just update openssl configuration file, no need to recompile anything

image

melroy89 commented 4 years ago

You can with nginx too ; just update openssl configuration file, no need to recompile anything

Maybe you want to share what kind of distro + version you are using and which version of openssl. And what you actually changed within the openssl.cnf file? And how your nginx config looks like?

I'm running Debian 10 (buster) server with OpenSSL v1.1.1g. My openssl config is located in /usr/lib/ssl btw.

ckaspers commented 4 years ago

You can with nginx too ; just update openssl configuration file, no need to recompile anything

I too would like to know how you made this possible with a "simple" edit to the config file.

My ssl.conf for Nginx looks like this, but it is still using 128 bit and secp256r1 for TLS 1.3 anyway. This means I score 90 on both Cipher Strength and Key Exchange, due to OpenSSL forcing them.

ssl_certificate /etc/letsencrypt/rsa-certs/fullchain.pem; ssl_certificate_key /etc/letsencrypt/rsa-certs/privkey.pem; ssl_certificate /etc/letsencrypt/ecc-certs/fullchain.pem; ssl_certificate_key /etc/letsencrypt/ecc-certs/privkey.pem; ssl_trusted_certificate /etc/letsencrypt/ecc-certs/chain.pem; ssl_dhparam /etc/ssl/certs/dhparam.pem; ssl_session_timeout 1d; ssl_session_cache shared:SSL:50m; ssl_session_tickets off; ssl_protocols TLSv1.3 TLSv1.2; ssl_ciphers 'TLS-CHACHA20-POLY1305-SHA256:TLS-AES-256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384'; ssl_ecdh_curve X448:secp521r1:secp384r1:prime256v1; ssl_prefer_server_ciphers on; ssl_stapling on; ssl_stapling_verify on;

wibimaster commented 4 years ago

@danger89 @ckaspers I'm using :

I just updated the /etc/ssl/openssl.cnf file with :

openssl_conf = default_conf

[default_conf]
ssl_conf = ssl_sect

[ssl_sect]
system_default = system_default_sect

[system_default_sect]
MinProtocol = TLSv1.2
CipherString = DEFAULT@SECLEVEL=2
Ciphersuites = TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
Options = ServerPreference,PrioritizeChaCha

Sources :

Beware that this update should be done at the start of the configuration file (at the end it doesn't work). I wrote it just before "[ new_oids ]" section.

EDIT

If you want my nginx configuration file :

ssl_protocols TLSv1.3 TLSv1.2;
ssl_dhparam /etc/nginx/dhparam.pem;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_prefer_server_ciphers on;
ssl_ecdh_curve secp521r1:secp384r1;
ssl_ciphers "ALL:!AES128:!CAMELLIA128:!CAMELLIA:!ARIA128:!RSA:!SEED:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!3DES:!MD5:!PSK:!DHE-RSA-AES256:!ECDHE-RSA-AES256-SHA384:!DHE-RSA-AES256-SHA256:!ECDHE-RSA-AES256-SHA:!DHE-RSA-AES256-SHA:@STRENGTH";
ckaspers commented 4 years ago

@wibimaster

No matter what I do, the server keeps forcing the mandatory TLS_AES_128_GCM_SHA256 cipher. I even tried fully copying your configuration and rebooting the server, it still stays enabled.

To be honest, SSL Labs should just change their system to give us 100% with this cipher enabled.

axieum commented 4 years ago

Just tried this, I edited both openssl.cnf and openssl.cnf.dist, to no avail. Using OpenSSL 1.1.1g.

melroy89 commented 4 years ago

Just tried this, I edited both openssl.cnf and openssl.cnf.dist, to no avail. Using OpenSSL 1.1.1g.

Depending on the distribution the files could be located somewhere else like in my case /usr/lib/ssl. Assuming the solution proposed by wibimaster works.

wibimaster commented 4 years ago

You can use openssl version -a | grep OPENSSLDIR to determinate which file you have to patch. In my case, output is /usr/lib/ssl, and a simple ls -l on this folder shows that openssl.cnf is a symlink to /etc/ssl/openssl.cnf.

@ckaspers Did you patch at the start of the file and not the bottom ?

Here is a default openssl.cnf, without comments, and with the patch you can see : https://pastebin.com/ELCwTHB2

Of course my certificate was 4096 bits and dhparam too, to get full 100%.

I didn't reboot my server, only restarted nginx

melroy89 commented 4 years ago

Of course my certificate was 4096 bits and dhparam too, to get full 100%.

You triggered me here. I think you creating self-signed certificate using openssl, is that right? While others may use Let's encrypt as CA ;). Even then, you can create 4096 bits certificates via Let's Encrypt. I do it already. Change your /etc/letsencrypt/cli.ini file, like so:

image

wibimaster commented 4 years ago

Of course my certificate was 4096 bits and dhparam too, to get full 100%.

You triggered me here. I think you creating self-signed certificate using openssl, is that right? While others may use Let's encrypt as CA ;). Even then, you can create 4096 bits certificates via Let's Encrypt. I do it already. Change your /etc/letsencrypt/cli.ini file, like so:

image

Oh no, I'm using Letsencrypt too ;) But for TLSv1.3, nginx use openssl to determinate cipher suites ; just patch openssl configuration file and it rocks, nginx follow it :)

wibimaster commented 4 years ago

Maybe you can check your openssl configuration after editing it : openssl ciphers -s -v | grep 1.3

It should output :

TLS_AES_256_GCM_SHA384  TLSv1.3 Kx=any      Au=any  Enc=AESGCM(256) Mac=AEAD
TLS_CHACHA20_POLY1305_SHA256 TLSv1.3 Kx=any      Au=any  Enc=CHACHA20/POLY1305(256) Mac=AEAD

Be aware that this modification is system wide. If you want to edit this configuration only for nginx, you have to create another openssl configuration file and modify nginx service to use it (environement variable)

ckaspers commented 4 years ago

@wibimaster

I checked and my path is also /usr/lib/ssl/openssl.cnf which is a symlink to /etc/ssl/openssl.cnf. I added the exact same block of text in the exact same place as your file and restarted nginx.

If it makes any difference at all I am running Ubuntu 20.04 LTS on a Raspberry Pi 4B 4GB. And I'm running OpenSSL version 1.1.1g which is from the 21st of april 2020.

root@raspberrypi:/usr/lib/ssl# ls -l
total 4
lrwxrwxrwx 1 root root   14 Aug 20  2019 certs -> /etc/ssl/certs
drwxr-xr-x 2 root root 4096 May  9 22:55 misc
lrwxrwxrwx 1 root root   20 Apr 21 16:31 openssl.cnf -> /etc/ssl/openssl.cnf
lrwxrwxrwx 1 root root   16 Aug 20  2019 private -> /etc/ssl/private

root@raspberrypi:/usr/lib/ssl# openssl ciphers -s -v | grep 1.3
TLS_AES_256_GCM_SHA384  TLSv1.3 Kx=any      Au=any  Enc=AESGCM(256) Mac=AEAD
TLS_CHACHA20_POLY1305_SHA256 TLSv1.3 Kx=any      Au=any  Enc=CHACHA20/POLY1305(256) Mac=AEAD
TLS_AES_128_GCM_SHA256  TLSv1.3 Kx=any      Au=any  Enc=AESGCM(128) Mac=AEAD

Here's my openssl.cnf file: https://pastebin.com/w5Bxpnsp.

And this is my ssl.conf file in /etc/nginx:

ssl_certificate /etc/letsencrypt/rsa-certs/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/rsa-certs/privkey.pem;
ssl_certificate /etc/letsencrypt/ecc-certs/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/ecc-certs/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/ecc-certs/chain.pem;
ssl_dhparam /etc/ssl/certs/dhparam.pem;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
ssl_protocols TLSv1.3 TLSv1.2;
ssl_ciphers 'TLS-CHACHA20-POLY1305-SHA256:TLS-AES-256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384';
ssl_ecdh_curve secp521r1:secp384r1;
ssl_prefer_server_ciphers on;
ssl_stapling on;
ssl_stapling_verify on;

It just keeps forcing the "mandatory" 128 bit cipher for whatever reason...

mddvul22 commented 4 years ago

Respectfully, the last two days of comments seem unrelated to the bug report about Qualys' handing of TLS 1.3 scoring. We all want this solved. But it doesn't seem to me that this bug report is the place to figure out a workaround, that doesn't involve Qualys actually fixing the problem.

wibimaster commented 4 years ago

@ckaspers you missed a thing into openssl configuration, read carefully my comment :

openssl_conf = default_conf

@mddvul22 Sure, but if Qualys think that 128 is insecure for TLSv1.3 too, we have to find a workaround :/

shoujii commented 4 years ago

It’s really funny, I opened this issue nearly 2 years ago and it still persists.

I’m really sad that there is no solution without less or more dirty workarounds:/

axieum commented 4 years ago

I'm really sad that there is no solution

@shoujii It is quite disappointing, isn't it.

I have several times to implement @wibimaster's solution, perhaps you could upgrade your OpenSSL to the latest 1.1.1g (over h), and see if your workaround remains?

The only difference I can see between our configurations is the:

[ CA_default ]
dir = /etc/ssl
ckaspers commented 4 years ago

@wibimaster hmm, I swear I had that in there last time I tested though. I get the correct ciphers now with openssl ciphers -s -v | grep 1.3.

I don't know what changed, but everything is working correctly and I have 100% now.

wibimaster commented 4 years ago

@wibimaster hmm, I swear I had that in there last time I tested though. I get the correct ciphers now with openssl ciphers -s -v | grep 1.3.

I don't know what changed, but everything is working correctly and I have 100% now.

Glad to see that it works for you :)

About all this thread : I'm ABSOLUTELY NOT a security expert. Before TLSv1.3 story, nobody says "what, we have to change nginx configuration file to have 100 % ? Dirty hack !"

If Qualys says "Having a 128 bit in ciphers list is not secure", I follow them. If it's not quite as easy as just update nginx.conf, it's not Qualys fault ; it's openssl that closes the possibility to update this ciphers list from external tools (if I understood correctly).

But you can update this configuration, you can have a specific openssl configuration file for nginx if you don't want to have this patch system-wide, and you don't have to build anything. If it's related to newer openssl or nginx version that the ones you have, just update them ; someone really concerned with security tries to stay up to date :)

For this specific thread, you can have 100% with TLSv1.3 quite easily.

Maybe another thread with "TLSv1.3 with 128 bits in ciphers list should be considered secured" could be opened, but I'm not an expert. Maybe an issue could be opened between openssl and nginx to override standard configuration RFC compliant like for TLSv1.2, but it's not into Qualys spectrum :)

axieum commented 4 years ago

Managed to get it working by purging my OpenSSL

Arch Linux 5.6.13.a-1-hardened x86_64 OpenSSL 1.1.1g 21 Apr 2020

rm -rf /etc/ssl/*
pacman -S openssl

..creating a /etc/ssl/cipherquites.cnf file - for organisation

# Ciphersuites Configuration

MinProtocol             = TLSv1.2
CipherString            = DEFAULT@SECLEVEL=2
Ciphersuites            = TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
Options                 = ServerPreference,PrioritizeChaCha

..inserting the following lines into /etc/ssl/openssl.cnf

@@ -11,6 +11,17 @@
# defined.
HOME                   = .

+openssl_conf           = default_conf
+
+[ default_conf ]
+ssl_conf               = ssl_section
+
+[ ssl_section ]
+system_default         = ssl_sys_section
+
+[ ssl_sys_section ]
+.include               /etc/ssl/ciphersuites.cnf
+
# Extra OBJECT IDENTIFIER info:
#oid_file              = $ENV::HOME/.oid
oid_section            = new_oids

..and finally restarting Nginx (a reload didn't seem to work for me).

systemctl restart nginx

If it doesn't immediately work, try do a reboot.

Results

![image](https://user-images.githubusercontent.com/7577851/82657125-2fc20e00-9c68-11ea-8267-9c8f068509a8.png) ![image](https://user-images.githubusercontent.com/7577851/82657191-4e280980-9c68-11ea-86af-c51cd621f917.png)

Nginx TLS configurations

**`/etc/nginx/tls.conf`**: ```conf ssl_session_cache shared:SSL:10m; ssl_session_timeout 10m; ssl_session_tickets off; ssl_protocols TLSv1.3 TLSv1.2; ssl_prefer_server_ciphers on; ssl_ecdh_curve secp521r1:secp384r1; ssl_ciphers "ECDHE+ECDSA+CHACHA20:ECDHE+ECDSA+AESGCM:!AES128"; ssl_stapling on; ssl_stapling_verify on; resolver 1.1.1.1 1.0.0.1 valid=300s; resolver_timeout 5s; add_header Expect-CT "enforce; max-age=2592000; report-uri=\"https://tls.example.net\"" always; add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always; ```

Thanks @wibimaster and @ckaspers! 🎉

ertuzio commented 4 years ago

Sorry but this doesn't give all 100%

can you reupload your screen-shot with date?

wibimaster commented 4 years ago

Sorry but this doesn't give all 100%

can you reupload your screen-shot with date?

Which one ? Mine or Axieum's ?

ertuzio commented 4 years ago

Axieum's Now I tried your ciphers @wibimaster and it works.... all 100% and A+

ALL:!AES128:!CAMELLIA128:!CAMELLIA:!ARIA128:!RSA:!SEED:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!3DES:!MD5:!PSK:!DHE-RSA-AES256:!ECDHE-RSA-AES256-SHA384:!DHE-RSA-AES256-SHA256:!ECDHE-RSA-AES256-SHA:!DHE-RSA-AES256-SHA:@STRENGTH

with updated etc/ssl/openssl.cnf

abradshaw commented 4 years ago

@wibimaster comment from 18th May did the trick for me, on CentOS8 - just needed to alter 1 line in the openssl config

Here is the part of my ansible playbook that takes care of this

- name: Ensure older ciphers cant be used by openssl
  lineinfile:
    path: /etc/crypto-policies/back-ends/opensslcnf.config
    regexp: '^Ciphersuites'
    line: 'Ciphersuites = TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256'
mddvul22 commented 4 years ago

TLS_AES_128_GCM_SHA256 is a required cipher for TLS 1.3. RFC 8446 mandates it. In fact, there is a considerable argument to be made that AES 128 is actually more secure than something using AES 256. (Link) Openssl's default configuration is correct here. The correct fix, in the end, is for Qualys to correct their scoring. You guys are arguably weakening your security by removing TLS_AES_128_GCM_SHA256 -- just so that you can get 100%.

TCHessen commented 4 years ago

You're right that TLS_AES_128_GCM_SHA256 is a mandated cipher for a TLS 1.3 implementation, but no one says my server has to provide it. Suppose an RFC for 1.3 requires a CIPHER with DES and 256 RSA, would you provide it? But I agree that an AES128 should not lower the rating to 90% because it is not actually insecure, but don't argue with an RFC that doesn't guarantee any security.

ygoe commented 3 years ago

Folks, just scan a Google website (the only one I could find that uses ECDSA certificates instead of RSA) and look at their results. It's a plain B. That's not even green anymore. So I, for one, am quite happy to get an A with some 90% scores. I don't see the difference between 128 and 256 bit encryption, which translates roughly to "practically unbreakable" and "practically unbreakable".

beatquantum commented 3 years ago

I just wish to confirm that the solution from wibimaster works on openssl 1.1.1i and nginx 1.19.6. Fyi - I used secp384r1 Thank you!

SagePtr commented 3 years ago

Note: starting from nginx 1.19.4 and later you can specify TLSv1.3 cipher suites right in the nginx config:

ssl_conf_command Ciphersuites TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256;

I used this to achieve 100/100/100/100 (in conjunction with EC P-384 certificate signed by E1 Let's Encrypt intermediate):

ssl_protocols     TLSv1.2 TLSv1.3;
ssl_ciphers       ECDH+AESGCM+AES256:ECDH+CHACHA20; # TLSv1.2
ssl_conf_command  Ciphersuites TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256; # TLSv1.3
ssl_ecdh_curve    secp384r1;

It screws some old clients, and p384 is much slower than p256 (on my VPS it's even twice slower than rsa2048), so it's better not to use this in production, unless you are extremely paranoid about the possibility of cracking AES-128 and/or EC P-256.

beatquantum commented 3 years ago

Huge thanks @SagePtr - Good to know nginx can specify the ciphers directly; so we do not need to play with openssl.cnf.

I liked your comments that helped to research further. The "old clients" are actually include Chrome 49 (for Win XP), Firefox 31 (for Win 7), Safari 8 (for Yosemite) and older versions and it makes no sense to use them in August 2021. So the issue of incompatibility is effectively for visitors using Android 6 or older; which in 2021 is less than 5% of the total Android population anyway and no longer receive security updates. So each one has to take a business decision for themselves, whether to provide backward compatibility with obsolete browsers and operating systems.

As my servers CPU usage is very low and the pagespeed result is acceptable (with p384); there was no need to use p256.

I find it is difficult to distinguish between extreme paranoids, score junkies and good cyber practices. Their venn diagrams overlap!

HepplerDotNet commented 3 years ago

@SagePtr thanks, with this config I get 100/100/100/100. But this also disables 0-RTT. Any idea which ECDH curve can be used to stay on 100 Key Exchange and enable 0-RTT? Commenting out ssl_ecdh_curve enables 0-RTT, but cuts Key Echange down to 90

SagePtr commented 3 years ago

@SagePtr thanks, with this config I get 100/100/100/100. But this also disables 0-RTT. Any idea which ECDH curve can be used to stay on 100 Key Exchange and enable 0-RTT? Commenting out ssl_ecdh_curve enables 0-RTT, but cuts Key Echange down to 90

Tested with openssl s_client and figured it out: when i specify -curve secp384r1 parameter in the client, the 0-RTT data is accepted, but when i don't specify any curve list, the 0-RTT data is rejected. If i specify X25519 among ssl_ecdh_curve list (on the server) - 0-RTT works anyway, but drops kex score to 90. Ideally, 0-RTT should not be used in a strong crypto setup, as it slightly reduces the security of the first packet for the sake of a faster handshake. UPD: I tested on real browsers (Firefox and Chrome). During the handshake, Firefox sends two key share entries: computed with x25519 and prime256v1. Chrome sends two key shares as well, but one is GREASE, the second is x25519. They don't memoize what curve was used during the last handshake. So, in both browsers, if the server doesn't allow x25519, it replies with "Hello Retry Request" screwing up 0-RTT and 1-RTT speed as well. That's the another reason why removing x25519 from the curve list makes TLS session establishment slight slower (besides the lack of secp384r1 low-level optimizations in OpenSSL).

HepplerDotNet commented 3 years ago

@SagePtr thanks! My setup doesn't really require high security. So I stick with: ssl_ecdh_curve X25519:secp521r1:secp384r1; That way 0-RTT works and a Key Ex 90 is still fine.