From 231a29cdfd508a9f2a751e8a5642beccc38d3fef Mon Sep 17 00:00:00 2001 From: Dirk Wetter Date: Sat, 14 Sep 2019 10:41:54 +0200 Subject: [PATCH 1/2] Deprecate TLS 1.0 and TLS 1.1 This commit addresses #1251 and gives a slight warning when still using those protocols as government standards are or are at least to expect also to deprecate those protocols. PCI DSS requires not to use TLS 1.0 anymore and browser vendors supposedly will deprecate TLS 1.0/1.1 next year. This is a WIP for testing. It was committed already in May (22ad490ea7b2868a4fd45862ca0bf8a3d8f24ea6) but somehow it was lost. Comments would be appeciated. Open: - how to treat non-HTTP protocols - TLS 1.3 only hosts will mark the absence of TLS 1.2 as a medium finding --- testssl.sh | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/testssl.sh b/testssl.sh index ac90014..720c4b2 100755 --- a/testssl.sh +++ b/testssl.sh @@ -1702,9 +1702,9 @@ check_revocation_crl() { [[ -n "$GOOD_CA_BUNDLE" ]] || return 0 scheme="$(tolower "${crl%%://*}")" # The code for obtaining CRLs only supports LDAP, HTTP, and HTTPS URLs. - [[ "$scheme" == "http" ]] || [[ "$scheme" == "https" ]] || [[ "$scheme" == "ldap" ]] || return 0 + [[ "$scheme" == http ]] || [[ "$scheme" == https ]] || [[ "$scheme" == ldap ]] || return 0 tmpfile=$TEMPDIR/${NODE}-${NODEIP}.${crl##*\/} || exit $ERR_FCREATE - if [[ "$scheme" == "ldap" ]]; then + if [[ "$scheme" == ldap ]]; then ldap_get "$crl" "$tmpfile" "$jsonID" success=$? else @@ -1737,7 +1737,7 @@ check_revocation_crl() { fileout "$jsonID" "OK" "not revoked" else retcode=$(awk '/error [1-9][0-9]? at [0-9]+ depth lookup:/ { if (!found) {print $2; found=1} }' "${tmpfile%%.crl}.err") - if [[ "$retcode" == "23" ]]; then # see verify_retcode_helper() + if [[ "$retcode" == 23 ]]; then # see verify_retcode_helper() out ", " pr_svrty_critical "revoked" fileout "$jsonID" "CRITICAL" "revoked" @@ -5027,8 +5027,8 @@ run_protocols() { run_prototest_openssl "-tls1" fi case $? in - 0) outln "offered" - fileout "$jsonID" "INFO" "offered" + 0) pr_svrty_low "offered" ; outln " (deprecated)" + fileout "$jsonID" "LOW" "offered (deprecated)" latest_supported="0301" latest_supported_string="TLSv1.0" add_tls_offered tls1 yes @@ -5101,8 +5101,8 @@ run_protocols() { run_prototest_openssl "-tls1_1" fi case $? in - 0) outln "offered" - fileout "$jsonID" "INFO" "offered" + 0) pr_svrty_low "offered" ; outln " (deprecated)" + fileout "$jsonID" "LOW" "offered (deprecated)" latest_supported="0302" latest_supported_string="TLSv1.1" add_tls_offered tls1_1 yes @@ -5375,33 +5375,35 @@ run_protocols() { latest_supported_string="TLSv1.3" add_tls_offered tls1_3 yes ;; - 1) out "not offered" + 1) pr_svrty_low "not offered" if ! "$using_sockets" || [[ -z $latest_supported ]]; then outln - fileout "$jsonID" "INFO" "not offered" + fileout "$jsonID" "LOW" "not offered" else prln_svrty_critical " -- connection failed rather than downgrading to $latest_supported_string" fileout "$jsonID" "CRITICAL" "connection failed rather than downgrading to $latest_supported_string" fi add_tls_offered tls1_3 no ;; - 2) out "not offered" - if [[ "$DETECTED_TLS_VERSION" == 0300 ]]; then + 2) if [[ "$DETECTED_TLS_VERSION" == 0300 ]]; then detected_version_string="SSLv3" elif [[ "$DETECTED_TLS_VERSION" == 03* ]]; then detected_version_string="TLSv1.$((0x$DETECTED_TLS_VERSION-0x0301))" fi if [[ "$DETECTED_TLS_VERSION" == "$latest_supported" ]]; then [[ $DEBUG -ge 1 ]] && tm_out " -- downgraded" - outln - fileout "$jsonID" "INFO" "not offered and downgraded to a weaker protocol" + outln "not offered and downgraded to a weaker protocol" + fileout "$jsonID" "INFO" "not offered + downgraded to weaker protocol" elif [[ "$DETECTED_TLS_VERSION" == 03* ]] && [[ 0x$DETECTED_TLS_VERSION -lt 0x$latest_supported ]]; then + out "not offered" prln_svrty_critical " -- server supports $latest_supported_string, but downgraded to $detected_version_string" fileout "$jsonID" "CRITICAL" "not offered, and downgraded to $detected_version_string rather than $latest_supported_string" elif [[ "$DETECTED_TLS_VERSION" == 03* ]] && [[ 0x$DETECTED_TLS_VERSION -gt 0x0304 ]]; then + out "not offered" prln_svrty_critical " -- server responded with higher version number ($detected_version_string) than requested by client" fileout "$jsonID" "CRITICAL" "not offered, server responded with higher version number ($detected_version_string) than requested by client" else + out "not offered" prln_svrty_critical " -- server responded with version number ${DETECTED_TLS_VERSION:0:2}.${DETECTED_TLS_VERSION:2:2}" fileout "$jsonID" "CRITICAL" "server responded with version number ${DETECTED_TLS_VERSION:0:2}.${DETECTED_TLS_VERSION:2:2}" fi From 7ec3c6ab997b012b1518903137d84043cf9825a8 Mon Sep 17 00:00:00 2001 From: Dirk Wetter Date: Sat, 14 Sep 2019 17:56:31 +0200 Subject: [PATCH 2/2] Don't penalize TLS 1.2 is not available if TLS 1.3 is supported ... and thus this commit addresses #916. It does that via a (quite) pre-test which checks for a general availabilty of TLS 1.3 before the TLS 1.2 protocol test is being run and decides based on that how a missing TLS 1.2 will be echoed. Later on the complete TLS 1.3 test will be continued using the results from the TLS 1.3 pre-test. --- testssl.sh | 87 ++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 55 insertions(+), 32 deletions(-) diff --git a/testssl.sh b/testssl.sh index 720c4b2..b83e5c1 100755 --- a/testssl.sh +++ b/testssl.sh @@ -4866,7 +4866,8 @@ run_protocols() { local lines nr_ciphers_detected local tls13_ciphers_to_test="" local i drafts_offered="" drafts_offered_str="" supported_versions debug_recomm="" - local -i ret=0 subret=0 + local -i ret=0 subret=0 ret_val_tls13=0 + local offers_tls13=false local jsonID="SSLv2" outln; pr_headline " Testing protocols " @@ -5170,6 +5171,39 @@ run_protocols() { ;; esac + # Now, we are doing a basic/pre test for TLS 1.3 in order not to penalize servers (medium) + # running TLS 1.3 only when TLS 1.2 is not offered. 0 and 5 are the return codes for + # TLS 1.3 support (kind of, including deprecated pre-versions of TLS 1.3) + if "$using_sockets"; then + # Need to ensure that at most 128 ciphers are included in ClientHello. + # If the TLSv1.2 test was successful, then use the 5 TLSv1.3 ciphers + # plus the cipher selected in the TLSv1.2 test. If the TLSv1.2 test was + # not successful, then just use the 5 TLSv1.3 ciphers plus the list of + # ciphers used in all of the previous tests ($TLS_CIPHER). + if [[ $subret -eq 0 ]] || [[ $subret -eq 2 ]]; then + tls13_ciphers_to_test="$(get_cipher "$TEMPDIR/$NODEIP.parse_tls_serverhello.txt")" + if [[ "$tls13_ciphers_to_test" == TLS_* ]] || [[ "$tls13_ciphers_to_test" == SSL_* ]]; then + tls13_ciphers_to_test="$(rfc2hexcode "$tls13_ciphers_to_test")" + else + tls13_ciphers_to_test="$(openssl2hexcode "$tls13_ciphers_to_test")" + fi + fi + if [[ ${#tls13_ciphers_to_test} -eq 9 ]]; then + tls13_ciphers_to_test="$TLS13_CIPHER, ${tls13_ciphers_to_test:2:2},${tls13_ciphers_to_test:7:2}, 00,ff" + else + tls13_ciphers_to_test="$TLS13_CIPHER,$TLS_CIPHER" + fi + tls_sockets "04" "$tls13_ciphers_to_test" + else + run_prototest_openssl "-tls1_3" + fi + ret_val_tls13=$? + if [[ $ret_val_tls13 -eq 0 ]] || [[ $ret_val_tls13 -eq 5 ]]; then + offers_tls13=true # This variable comes in handy for further if statements below + fi + # Done with pretesting TLS 1.3. Normally we should/could reverse the order for the protocols -- or + # keep the order and mute the output, until we can make a final verdict + pr_bold " TLS 1.2 "; jsonID="TLS1_2" if "$using_sockets"; then @@ -5190,19 +5224,31 @@ run_protocols() { latest_supported="0303" latest_supported_string="TLSv1.2" add_tls_offered tls1_2 yes - ;; # GCM cipher in TLS 1.2: very good! - 1) pr_svrty_medium "not offered" - add_tls_offered tls1_2 no + ;; # GCM cipher in TLS 1.2: very good! + 1) add_tls_offered tls1_2 no + if "$offers_tls13"; then + out "not offered" + else + pr_svrty_medium "not offered" + fi if ! "$using_sockets" || [[ -z $latest_supported ]]; then outln - fileout "$jsonID" "MEDIUM" "not offered" # no GCM, penalty + if "$offers_tls13"; then + fileout "$jsonID" "INFO" "not offered" + else + fileout "$jsonID" "MEDIUM" "not offered" # TLS 1.3, no TLS 1.2 --> no GCM, penalty + fi else prln_svrty_critical " -- connection failed rather than downgrading to $latest_supported_string" fileout "$jsonID" "CRITICAL" "connection failed rather than downgrading to $latest_supported_string" fi ;; - 2) pr_svrty_medium "not offered" - add_tls_offered tls1_2 no + 2) add_tls_offered tls1_2 no + if "$offers_tls13"; then + out "not offered" + else + pr_svrty_medium "not offered" + fi if [[ "$DETECTED_TLS_VERSION" == 0300 ]]; then detected_version_string="SSLv3" elif [[ "$DETECTED_TLS_VERSION" == 03* ]]; then @@ -5229,7 +5275,7 @@ run_protocols() { fi ;; 3) out "not offered, " - fileout "$jsonID" "OK" "not offered" + fileout "$jsonID" "INFO" "not offered" add_tls_offered tls1_2 no pr_warning "TLS downgraded to STARTTLS plaintext"; outln fileout "$jsonID" "WARN" "TLS downgraded to STARTTLS plaintext" @@ -5260,30 +5306,7 @@ run_protocols() { pr_bold " TLS 1.3 "; jsonID="TLS1_3" - if "$using_sockets"; then - # Need to ensure that at most 128 ciphers are included in ClientHello. - # If the TLSv1.2 test was successful, then use the 5 TLSv1.3 ciphers - # plus the cipher selected in the TLSv1.2 test. If the TLSv1.2 test was - # not successful, then just use the 5 TLSv1.3 ciphers plus the list of - # ciphers used in all of the previous tests ($TLS_CIPHER). - if [[ $subret -eq 0 ]] || [[ $subret -eq 2 ]]; then - tls13_ciphers_to_test="$(get_cipher "$TEMPDIR/$NODEIP.parse_tls_serverhello.txt")" - if [[ "$tls13_ciphers_to_test" == TLS_* ]] || [[ "$tls13_ciphers_to_test" == SSL_* ]]; then - tls13_ciphers_to_test="$(rfc2hexcode "$tls13_ciphers_to_test")" - else - tls13_ciphers_to_test="$(openssl2hexcode "$tls13_ciphers_to_test")" - fi - fi - if [[ ${#tls13_ciphers_to_test} -eq 9 ]]; then - tls13_ciphers_to_test="$TLS13_CIPHER, ${tls13_ciphers_to_test:2:2},${tls13_ciphers_to_test:7:2}, 00,ff" - else - tls13_ciphers_to_test="$TLS13_CIPHER,$TLS_CIPHER" - fi - tls_sockets "04" "$tls13_ciphers_to_test" - else - run_prototest_openssl "-tls1_3" - fi - case $? in + case $ret_val_tls13 in 0) if ! "$using_sockets"; then prln_svrty_best "offered (OK)" fileout "$jsonID" "OK" "offered"