diff --git a/CREDITS.md b/CREDITS.md index 6b6651b..967c0bb 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -21,9 +21,11 @@ - JSON and CSV output - Client simulations -* dcooper16 +* David Cooper - Detection + output of multiple certificates - several cleanups of server certificate related stuff + - improved parsing of TLS ServerHello messages + - speed improvements when testing all ciphers * Jean Marsault - client auth: ideas, code snipplets diff --git a/testssl.sh b/testssl.sh index 86a4795..bb66621 100755 --- a/testssl.sh +++ b/testssl.sh @@ -324,14 +324,14 @@ pr_liteblueln() { pr_liteblue "$1"; outln; } pr_blue() { [[ "$COLOR" -eq 2 ]] && ( "$COLORBLIND" && out "\033[1;32m$1" || out "\033[1;34m$1" ) || out "$1"; pr_off; } # used for head lines of single tests pr_blueln() { pr_blue "$1"; outln; } -pr_warning() { [[ "$COLOR" -eq 2 ]] && out "\033[0;35m$1" || pr_underline "$1"; pr_off; } # litemagentai | local problem: one test cannot be done -pr_warningln() { pr_warning "$1"; outln; } -pr_magenta() { [[ "$COLOR" -eq 2 ]] && out "\033[1;35m$1" || pr_underline "$1"; pr_off; } # Fatal error: quitting because of this! +pr_warning() { [[ "$COLOR" -eq 2 ]] && out "\033[0;35m$1" || pr_underline "$1"; pr_off; } # some local problem: one test cannot be done +pr_warningln() { pr_warning "$1"; outln; } # litemagenya +pr_magenta() { [[ "$COLOR" -eq 2 ]] && out "\033[1;35m$1" || pr_underline "$1"; pr_off; } # fatal error: quitting because of this! pr_magentaln() { pr_magenta "$1"; outln; } -pr_litecyan() { [[ "$COLOR" -eq 2 ]] && out "\033[0;36m$1" || out "$1"; pr_off; } # not yet used +pr_litecyan() { [[ "$COLOR" -eq 2 ]] && out "\033[0;36m$1" || out "$1"; pr_off; } # not yet used pr_litecyanln() { pr_litecyan "$1"; outln; } -pr_cyan() { [[ "$COLOR" -eq 2 ]] && out "\033[1;36m$1" || out "$1"; pr_off; } # additional hint +pr_cyan() { [[ "$COLOR" -eq 2 ]] && out "\033[1;36m$1" || out "$1"; pr_off; } # additional hint pr_cyanln() { pr_cyan "$1"; outln; } pr_litegreyln() { pr_litegrey "$1"; outln; } @@ -375,8 +375,11 @@ pr_headlineln() { pr_headline "$1" ; outln; } pr_squoted() { out "'$1'"; } pr_dquoted() { out "\"$1\""; } -local_problem_ln() { pr_warningln "Local problem: $1"; } local_problem() { pr_warning "Local problem: $1"; } +local_problem_ln() { pr_warningln "Local problem: $1"; } + +fixme() { pr_warning "fixme: $1"; } +fixme() { pr_warningln "fixme: $1"; } ### color switcher (see e.g. https://linuxtidbits.wordpress.com/2008/08/11/output-color-on-bash-scripts/ ### http://www.tldp.org/HOWTO/Bash-Prompt-HOWTO/x405.html @@ -642,17 +645,17 @@ runs_HTTP() { *) if $CLIENT_AUTH; then out "certificate based authentication => skipping all HTTP checks" echo "certificate based authentication => skipping all HTTP checks" >$TMPFILE - fileout "client_auth" "WARN" "certificate based authentication => skipping all HTTP checks" + fileout "client_auth" "INFO" "certificate based authentication => skipping all HTTP checks" else out " Couldn't determine what's running on port $PORT" if $ASSUMING_HTTP; then SERVICE=HTTP out " -- ASSUMING_HTTP set though" - fileout "service" "WARN" "Couldn't determine service, --ASSUMING_HTTP set" + fileout "service" "DEBUG" "Couldn't determine service, --ASSUMING_HTTP set" ret=0 else out ", assuming no HTTP service => skipping all HTTP checks" - fileout "service" "WARN" "Couldn't determine service, skipping all HTTP checks" + fileout "service" "DEBUG" "Couldn't determine service, skipping all HTTP checks" ret=1 fi fi @@ -1011,7 +1014,7 @@ run_hpkp() { out "\n$spaces" pr_svrty_high " No matching key for pins found " out "(CAs pinned? -- not checked for yet)" - fileout "hpkp_keymatch" "WARN" "The TLS key does not match any key pinned in the HPKP header. If you pinned a CA key you can ignore this" + fileout "hpkp_keymatch" "DEBUG" "The TLS key does not match any key pinned in the HPKP header. If you pinned a CA key you can ignore this" fi else out "--" @@ -2242,6 +2245,12 @@ run_prototest_openssl() { # 7: no local support } +# idempotent function to add SSL/TLS protocols. It should ease testing +# PROTOS_OFFERED's content is in openssl terminology +add_tls_offered() { + grep -w "$1" <<< "$PROTOS_OFFERED" || PROTOS_OFFERED+="$1 " +} + # the protocol check needs to be revamped. It sucks, see above run_protocols() { @@ -2281,6 +2290,7 @@ run_protocols() { 0) pr_svrty_criticalln "offered (NOT ok)" fileout "sslv2" "NOT ok" "SSLv2 is offered (NOT ok)" + add_tls_offered "ssl2" ;; 1) pr_done_bestln "not offered (OK)" @@ -2289,6 +2299,7 @@ run_protocols() { 5) pr_svrty_high "CVE-2015-3197: $supported_no_ciph2"; fileout "sslv2" "WARN" "CVE-2015-3197: SSLv2 is $supported_no_ciph2" + add_tls_offered "ssl2" ;; 7) fileout "sslv2" "INFO" "SSLv2 is not tested due to lack of local support" @@ -2306,6 +2317,7 @@ run_protocols() { 0) pr_svrty_highln "offered (NOT ok)" fileout "sslv3" "NOT ok" "SSLv3 is offered (NOT ok)" + add_tls_offered "ssl3" ;; 1) pr_done_bestln "not offered (OK)" @@ -2319,7 +2331,8 @@ run_protocols() { fileout "sslv3" "WARN" "SSLv3 is $supported_no_ciph1" pr_svrty_high "$supported_no_ciph2" outln "(may need debugging)" - ;; # protocol ok, but no cipher + add_tls_offered "ssl3" + ;; 7) fileout "sslv3" "INFO" "SSLv3 is not tested due to lack of local support" ;; # no local support @@ -2335,6 +2348,7 @@ run_protocols() { 0) outln "offered" fileout "tls1" "INFO" "TLSv1.0 is offered" + add_tls_offered "tls1" ;; # nothing wrong with it -- per se 1) outln "not offered" @@ -2345,10 +2359,12 @@ run_protocols() { [[ $DEBUG -eq 1 ]] && out " -- downgraded" outln fileout "tls1" "MEDIUM" "TLSv1.0 is not offered, and downgraded to SSL" + add_tls_offered "tls1" ;; 5) outln "$supported_no_ciph1" # protocol ok, but no cipher fileout "tls1" "WARN" "TLSv1.0 is $supported_no_ciph1" + add_tls_offered "tls1" ;; 7) fileout "tlsv1" "INFO" "TLSv1.0 is not tested due to lack of local support" @@ -2365,6 +2381,7 @@ run_protocols() { 0) outln "offered" fileout "tls1_1" "INFO" "TLSv1.1 is offered" + add_tls_offered "tls1_1" ;; # nothing wrong with it 1) outln "not offered" @@ -2379,6 +2396,7 @@ run_protocols() { 5) outln "$supported_no_ciph1" fileout "tls1_1" "WARN" "TLSv1.1 is $supported_no_ciph1" + add_tls_offered "tls1_1" ;; # protocol ok, but no cipher 7) fileout "tls1_1" "INFO" "TLSv1.1 is not tested due to lack of local support" @@ -2395,6 +2413,7 @@ run_protocols() { 0) pr_done_bestln "offered (OK)" fileout "tls1_2" "OK" "TLSv1.2 is offered (OK)" + add_tls_offered "tls1_2" ;; # GCM cipher in TLS 1.2: very good! 1) pr_svrty_mediumln "not offered" @@ -2409,11 +2428,13 @@ run_protocols() { 5) outln "$supported_no_ciph1" fileout "tls1_2" "WARN" "TLSv1.2 is $supported_no_ciph1" + add_tls_offered "tls1_2" ;; # protocol ok, but no cipher 7) fileout "tls1_2" "INFO" "TLSv1.2 is not tested due to lack of local support" ;; # no local support esac + return 0 } @@ -2760,7 +2781,7 @@ check_tls12_pref() { order="$cipher" tested_cipher="-$cipher" else - pr_warningln "fixme: something weird happened around line $((LINENO - 6))" + fixmeln "something weird happened around line $((LINENO - 6))" return 1 fi while true; do @@ -2780,6 +2801,8 @@ check_tls12_pref() { # second cipher set didn't succeed: we can just output everything out " $order" fi + + tmpfile_handle $FUNCNAME.txt return 0 } @@ -2815,7 +2838,7 @@ cipher_pref_check() { # thus we reduce the number of ciphers we throw at the server and put later everything together # see #189 # so far, this was only observed in TLS 1.2 - check_tls12_pref "$cipher" + order=$(check_tls12_pref "$cipher") else out " $cipher" # this is the first cipher for protocol while true; do @@ -2852,7 +2875,7 @@ cipher_pref_check() { order+=" $cipher" done outln - [[ -z $order ]] || fileout "order_spdy_$p" "INFO" "Default cipher order for SPDY protocol $p:order" + [[ -n $order ]] && fileout "order_spdy_$p" "INFO" "Default cipher order for SPDY protocol $p: $order" done fi @@ -4507,6 +4530,7 @@ sslv2_sockets() { [[ "$DEBUG" -ge 2 ]] && out " ($lines lines) " if [[ "$lines" -gt 1 ]]; then nr_ciphers_detected=$((V2_HELLO_CIPHERSPEC_LENGTH / 3)) + add_tls_offered "ssl2" if [[ 0 -eq "$nr_ciphers_detected" ]]; then pr_svrty_highln "supported but couldn't detect a cipher and vulnerable to CVE-2015-3197 "; fileout "sslv2" "NOT ok" "SSLv2 offered (NOT ok), vulnerable to CVE-2015-3197" @@ -4531,38 +4555,22 @@ sslv2_sockets() { # ARG1: TLS version low byte (00: SSLv3, 01: TLS 1.0, 02: TLS 1.1, 03: TLS 1.2) # ARG2: CIPHER_SUITES string socksend_tls_clienthello() { -#FIXME: redo this with all extensions! local tls_low_byte="$1" local tls_word_reclayer="03, 01" # the first TLS version number is the record layer and always 0301 -- except: SSLv3 local servername_hexstr len_servername len_servername_hex - local hexdump_format_str - local all_extensions - local len_sni_listlen len_sni_ext len_extension_hex - local cipher_suites len_ciph_suites len_ciph_suites_word + local hexdump_format_str part1 part2 + local all_extensions="" + local -i i j len_extension len_padding_extension len_all + local len_sni_listlen len_sni_ext len_extension_hex len_padding_extension_hex + local cipher_suites len_ciph_suites len_ciph_suites_byte len_ciph_suites_word local len_client_hello_word len_all_word - - #len_servername=$(echo ${#NODE}) - len_servername=${#NODE} - hexdump_format_str="$len_servername/1 \"%02x,\"" - servername_hexstr=$(printf $NODE | hexdump -v -e "${hexdump_format_str}" | sed 's/,$//') + local ecc_cipher_suite_found=false + local extension_signature_algorithms extension_heartbeat + local extension_session_ticket extension_next_protocol extensions_ecc extension_padding code2network "$2" # convert CIPHER_SUITES cipher_suites="$NW_STR" # we don't have the leading \x here so string length is two byte less, see next -#formatted example for SNI -#00 00 # extension server_name -#00 1a # length = the following +2 = server_name length + 5 -#00 18 # server_name list_length = server_name length +3 -#00 # server_name type (hostname) -#00 15 # server_name length -#66 66 66 66 66 66 2e 66 66 66 66 66 66 66 66 66 66 2e 66 66 66 target.mydomain1.tld # server_name target - - # convert lengths we need to fill in from dec to hex: - len_servername_hex=$(printf "%02x\n" $len_servername) - len_sni_listlen=$(printf "%02x\n" $((len_servername+3))) - len_sni_ext=$(printf "%02x\n" $((len_servername+5))) - len_extension_hex=$(printf "%02x\n" $((len_servername+9))) #FIXME: for TLS 1.2 and IIS servers we need extension_signature_algorithms!! - len_ciph_suites_byte=$(echo ${#cipher_suites}) let "len_ciph_suites_byte += 2" @@ -4572,6 +4580,136 @@ socksend_tls_clienthello() { len_ciph_suites_word="$LEN_STR" #[[ $DEBUG -ge 3 ]] && echo $len_ciph_suites_word + if [[ "$tls_low_byte" != "00" ]]; then + # Add extensions + + # Check to see if any ECC cipher suites are included in cipher_suites + for (( i=0; i=2)" [[ $DEBUG -ge 3 ]] && hexdump -C "$SOCK_REPLY_FILE" | head -1 ret=7 - fileout "DROWN" "MINOR_ERROR" "SSLv2: received a strange SSLv2 reply (rerun with DEBUG>=2)" + fileout "drown" "MINOR_ERROR" "SSLv2: received a strange SSLv2 reply (rerun with DEBUG>=2)" ;; 3) # vulnerable lines=$(count_lines "$(hexdump -C "$SOCK_REPLY_FILE" 2>/dev/null)") @@ -5466,16 +5565,16 @@ run_drown() { nr_ciphers_detected=$((V2_HELLO_CIPHERSPEC_LENGTH / 3)) if [[ 0 -eq "$nr_ciphers_detected" ]]; then pr_svrty_highln "CVE-2015-3197: SSLv2 supported but couldn't detect a cipher (NOT ok)"; - fileout "DROWN" "NOT ok" "SSLv2 offered (NOT ok), CVE-2015-3197: but could not detect a cipher" + fileout "drown" "NOT ok" "SSLv2 offered (NOT ok), CVE-2015-3197: but could not detect a cipher" else pr_svrty_criticalln "vulnerable (NOT ok), SSLv2 offered with $nr_ciphers_detected ciphers"; - fileout "DROWN" "NOT ok" "vulnerable (NOT ok), SSLv2 offered with $nr_ciphers_detected ciphers" + fileout "drown" "NOT ok" "vulnerable (NOT ok), SSLv2 offered with $nr_ciphers_detected ciphers" fi fi ret=1 ;; *) pr_done_bestln "not vulnerable on this port (OK)" - fileout "DROWN" "OK" "not vulnerable to DROWN" + fileout "drown" "OK" "not vulnerable to DROWN" outln "$spaces make sure you don't use this certificate elsewhere with SSLv2 enabled services" if [[ "$DEBUG" -ge 1 ]] || "$SHOW_CENSYS_LINK"; then # not advertising it as it after 5 tries and account is needed @@ -5750,7 +5849,7 @@ run_tls_truncation() { old_fart() { outln "Get precompiled bins or compile https://github.com/PeterMosmans/openssl ." - fileout "old_fart" "WARN" "Your $OPENSSL $OSSL_VER version is an old fart... . It doesn\'t make much sense to proceed. Get precompiled bins or compile https://github.com/PeterMosmans/openssl ." + fileout "old_fart" "ERROR" "Your $OPENSSL $OSSL_VER version is an old fart... . It doesn\'t make much sense to proceed. Get precompiled bins or compile https://github.com/PeterMosmans/openssl ." fatal "Your $OPENSSL $OSSL_VER version is an old fart... . It doesn\'t make much sense to proceed." -2 } @@ -7379,4 +7478,4 @@ fi exit $? -# $Id: testssl.sh,v 1.495 2016/06/07 11:02:57 dirkw Exp $ +# $Id: testssl.sh,v 1.496 2016/06/07 21:06:57 dirkw Exp $