From 2c4433367973dba8c69bf9661ebfd875ccf0792e Mon Sep 17 00:00:00 2001 From: Joshua Tauberer Date: Wed, 20 May 2015 19:41:04 -0400 Subject: [PATCH] compare tls ciphers against Mozilla's recommendations --- tests/tls.py | 42 ++++++++++++++++++++++++++++++++++++------ tests/tls_results.txt | 15 +++++++++++++++ 2 files changed, 51 insertions(+), 6 deletions(-) diff --git a/tests/tls.py b/tests/tls.py index 7eb7ee88..5b3d3552 100644 --- a/tests/tls.py +++ b/tests/tls.py @@ -49,14 +49,34 @@ SSLYZE = "sslyze-0_11-linux64/sslyze/sslyze.py" common_opts = ["--sslv2", "--sslv3", "--tlsv1", "--tlsv1_1", "--tlsv1_2", "--reneg", "--resum", "--hide_rejected_ciphers", "--compression", "--heartbleed"] +# Recommendations from Mozilla as of May 20, 2015 at +# https://wiki.mozilla.org/Security/Server_Side_TLS. +# +# The 'modern' ciphers support Firefox 27, Chrome 22, IE 11, +# Opera 14, Safari 7, Android 4.4, Java 8. Assumes TLSv1.1, +# TLSv1.2 only, though we may also be allowing TLSv3. +# +# The 'intermediate' ciphers support Firefox 1, Chrome 1, IE 7, +# Opera 5, Safari 1, Windows XP IE8, Android 2.3, Java 7. +# Assumes TLSv1, TLSv1.1, TLSv1.2. +# +# The 'old' ciphers bring compatibility back to Win XP IE 6. +MOZILLA_CIPHERS_MODERN = "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!3DES:!MD5:!PSK" +MOZILLA_CIPHERS_INTERMEDIATE = "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA" +MOZILLA_CIPHERS_OLD = "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA" + ###################################################################### -def sslyze(opts, port): +def sslyze(opts, port, ok_ciphers): # Print header. header = ("PORT %d" % port) print(header) print("-" * (len(header))) + # What ciphers should we expect? + ok_ciphers = subprocess.check_output(["openssl", "ciphers", ok_ciphers]).decode("utf8").strip().split(":") + + # Form the SSLyze connection string. connection_string = host + ":" + str(port) # Proxy via SSH. @@ -81,6 +101,16 @@ def sslyze(opts, port): # Print. print(out) + + # Pull out the accepted ciphers list for each SSL/TLS protocol + # version outputted. + accepted_ciphers = set() + for ciphers in re.findall(" Accepted:([\w\W]*?)\n *\n", out): + accepted_ciphers |= set(re.findall("\n\s*(\S*)", ciphers)) + print(" Should Not Offer: " + (", ".join(sorted(accepted_ciphers-set(ok_ciphers))) or "(none -- good)")) + print(" Could Also Offer: " + (", ".join(sorted(set(ok_ciphers)-accepted_ciphers)) or "(none -- good)")) + print() + finally: if proxy_proc: proxy_proc.terminate() @@ -92,16 +122,16 @@ def sslyze(opts, port): # Run SSLyze on various ports. # SMTP -sslyze(["--starttls=smtp"], 25) +sslyze(["--starttls=smtp"], 25, MOZILLA_CIPHERS_OLD) # SMTP Submission -sslyze(["--starttls=smtp"], 587) +sslyze(["--starttls=smtp"], 587, MOZILLA_CIPHERS_MODERN) # HTTPS -sslyze(["--http_get", "--chrome_sha1", "--hsts"], 443) +sslyze(["--http_get", "--chrome_sha1", "--hsts"], 443, MOZILLA_CIPHERS_INTERMEDIATE) # IMAP -sslyze([], 993) +sslyze([], 993, MOZILLA_CIPHERS_MODERN) # POP3 -sslyze([], 995) +sslyze([], 995, MOZILLA_CIPHERS_MODERN) diff --git a/tests/tls_results.txt b/tests/tls_results.txt index 65976bf0..0d10c9cb 100644 --- a/tests/tls_results.txt +++ b/tests/tls_results.txt @@ -122,6 +122,9 @@ PORT 25 EDH-RSA-DES-CBC3-SHA DH-2048 bits 112 bits 250 2.0.0 Ok DES-CBC3-SHA - 112 bits 250 2.0.0 Ok + Should Not Offer: DHE-RSA-SEED-SHA, ECDHE-RSA-RC4-SHA, EDH-RSA-DES-CBC3-SHA, RC4-MD5, RC4-SHA, SEED-SHA + Could Also Offer: DHE-DSS-AES128-GCM-SHA256, DHE-DSS-AES128-SHA, DHE-DSS-AES128-SHA256, DHE-DSS-AES256-GCM-SHA384, DHE-DSS-AES256-SHA, DHE-DSS-AES256-SHA256, DHE-DSS-CAMELLIA128-SHA, DHE-DSS-CAMELLIA256-SHA, ECDHE-ECDSA-AES128-GCM-SHA256, ECDHE-ECDSA-AES128-SHA, ECDHE-ECDSA-AES128-SHA256, ECDHE-ECDSA-AES256-GCM-SHA384, ECDHE-ECDSA-AES256-SHA, ECDHE-ECDSA-AES256-SHA384, ECDHE-ECDSA-DES-CBC3-SHA, SRP-3DES-EDE-CBC-SHA, SRP-AES-128-CBC-SHA, SRP-AES-256-CBC-SHA, SRP-DSS-3DES-EDE-CBC-SHA, SRP-DSS-AES-128-CBC-SHA, SRP-DSS-AES-256-CBC-SHA, SRP-RSA-3DES-EDE-CBC-SHA, SRP-RSA-AES-128-CBC-SHA, SRP-RSA-AES-256-CBC-SHA + PORT 587 -------- @@ -208,6 +211,9 @@ PORT 587 CAMELLIA128-SHA - 128 bits 250 2.0.0 Ok AES128-SHA - 128 bits 250 2.0.0 Ok + Should Not Offer: AES128-GCM-SHA256, AES128-SHA, AES128-SHA256, AES256-GCM-SHA384, AES256-SHA, AES256-SHA256, CAMELLIA128-SHA, CAMELLIA256-SHA, DHE-RSA-CAMELLIA128-SHA, DHE-RSA-CAMELLIA256-SHA, DHE-RSA-SEED-SHA, SEED-SHA + Could Also Offer: DHE-DSS-AES128-GCM-SHA256, DHE-DSS-AES128-SHA256, DHE-DSS-AES256-GCM-SHA384, DHE-DSS-AES256-SHA, ECDHE-ECDSA-AES128-GCM-SHA256, ECDHE-ECDSA-AES128-SHA, ECDHE-ECDSA-AES128-SHA256, ECDHE-ECDSA-AES256-GCM-SHA384, ECDHE-ECDSA-AES256-SHA, ECDHE-ECDSA-AES256-SHA384 + PORT 443 -------- @@ -275,6 +281,9 @@ PORT 443 DHE-RSA-AES128-SHA DH-2048 bits 128 bits HTTP 200 OK DES-CBC3-SHA - 112 bits HTTP 200 OK + Should Not Offer: (none -- good) + Could Also Offer: AES128-GCM-SHA256, AES128-SHA, AES128-SHA256, AES256-GCM-SHA384, AES256-SHA, AES256-SHA256, CAMELLIA128-SHA, CAMELLIA256-SHA, DHE-DSS-AES128-GCM-SHA256, DHE-DSS-AES128-SHA, DHE-DSS-AES128-SHA256, DHE-DSS-AES256-GCM-SHA384, DHE-DSS-AES256-SHA, DHE-DSS-AES256-SHA256, DHE-DSS-CAMELLIA128-SHA, DHE-DSS-CAMELLIA256-SHA, DHE-RSA-CAMELLIA128-SHA, DHE-RSA-CAMELLIA256-SHA, ECDHE-ECDSA-AES128-GCM-SHA256, ECDHE-ECDSA-AES128-SHA, ECDHE-ECDSA-AES128-SHA256, ECDHE-ECDSA-AES256-GCM-SHA384, ECDHE-ECDSA-AES256-SHA, ECDHE-ECDSA-AES256-SHA384, SRP-AES-128-CBC-SHA, SRP-AES-256-CBC-SHA, SRP-DSS-AES-128-CBC-SHA, SRP-DSS-AES-256-CBC-SHA, SRP-RSA-AES-128-CBC-SHA, SRP-RSA-AES-256-CBC-SHA + PORT 993 -------- @@ -342,6 +351,9 @@ _nassl.OpenSSLError - error:140940F5:SSL routines:ssl3_read_bytes:unexpected rec CAMELLIA128-SHA - 128 bits AES128-SHA - 128 bits + Should Not Offer: AES128-SHA, AES256-SHA, CAMELLIA128-SHA, CAMELLIA256-SHA, DHE-RSA-CAMELLIA128-SHA, DHE-RSA-CAMELLIA256-SHA + Could Also Offer: DHE-DSS-AES128-GCM-SHA256, DHE-DSS-AES128-SHA256, DHE-DSS-AES256-GCM-SHA384, DHE-DSS-AES256-SHA, DHE-RSA-AES128-GCM-SHA256, DHE-RSA-AES128-SHA256, DHE-RSA-AES256-GCM-SHA384, DHE-RSA-AES256-SHA256, ECDHE-ECDSA-AES128-GCM-SHA256, ECDHE-ECDSA-AES128-SHA, ECDHE-ECDSA-AES128-SHA256, ECDHE-ECDSA-AES256-GCM-SHA384, ECDHE-ECDSA-AES256-SHA, ECDHE-ECDSA-AES256-SHA384, ECDHE-RSA-AES128-GCM-SHA256, ECDHE-RSA-AES128-SHA256, ECDHE-RSA-AES256-GCM-SHA384, ECDHE-RSA-AES256-SHA384 + PORT 995 -------- @@ -409,3 +421,6 @@ _nassl.OpenSSLError - error:140940F5:SSL routines:ssl3_read_bytes:unexpected rec CAMELLIA128-SHA - 128 bits AES128-SHA - 128 bits + Should Not Offer: AES128-SHA, AES256-SHA, CAMELLIA128-SHA, CAMELLIA256-SHA, DHE-RSA-CAMELLIA128-SHA, DHE-RSA-CAMELLIA256-SHA + Could Also Offer: DHE-DSS-AES128-GCM-SHA256, DHE-DSS-AES128-SHA256, DHE-DSS-AES256-GCM-SHA384, DHE-DSS-AES256-SHA, DHE-RSA-AES128-GCM-SHA256, DHE-RSA-AES128-SHA256, DHE-RSA-AES256-GCM-SHA384, DHE-RSA-AES256-SHA256, ECDHE-ECDSA-AES128-GCM-SHA256, ECDHE-ECDSA-AES128-SHA, ECDHE-ECDSA-AES128-SHA256, ECDHE-ECDSA-AES256-GCM-SHA384, ECDHE-ECDSA-AES256-SHA, ECDHE-ECDSA-AES256-SHA384, ECDHE-RSA-AES128-GCM-SHA256, ECDHE-RSA-AES128-SHA256, ECDHE-RSA-AES256-GCM-SHA384, ECDHE-RSA-AES256-SHA384 +