From 33bda6408a3af367988cffdbfdbe585ef0faf5f8 Mon Sep 17 00:00:00 2001 From: Laine Gholson Date: Sat, 12 Dec 2015 18:20:57 -0600 Subject: [PATCH 1/8] Add HTTP2/ALPN support --- testssl.sh | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 65 insertions(+), 4 deletions(-) diff --git a/testssl.sh b/testssl.sh index 8f08aea..b05a432 100755 --- a/testssl.sh +++ b/testssl.sh @@ -160,6 +160,8 @@ IKNOW_FNAME=false # further global vars just declared here readonly NPN_PROTOs="spdy/4a2,spdy/3,spdy/3.1,spdy/2,spdy/1,http/1.1" +# alpn_protos needs to be space-separated, not comma-seperated +readonly ALPN_PROTOs="h2 h2-17 h2-16 h2-15 h2-14 spdy/3.1 http/1.1" TEMPDIR="" TMPFILE="" ERRFILE="" @@ -2429,6 +2431,24 @@ spdy_pre(){ return 0 } +http2_pre(){ + if [[ -n "$STARTTLS" ]]; then + [[ -n "$1" ]] && out "$1" + out "(HTTP/2 is a HTTP protocol and thus not tested here)" + return 1 + fi + if [[ -n "$PROXY" ]]; then + [[ -n "$1" ]] && pr_litemagenta " $1 " + pr_litemagenta "not tested as proxies do not support proxying it" + return 1 + fi + if ! $HAS_ALPN; then + local_problem "$OPENSSL doesn't support HTTP2/ALPN"; + return 7 + fi + return 0 +} + run_spdy() { local tmpstr local -i ret=0 @@ -2438,7 +2458,7 @@ run_spdy() { outln "\n" return 0 fi - $OPENSSL s_client -host $NODE -port $PORT $BUGS -nextprotoneg $NPN_PROTOs $ERRFILE >$TMPFILE + $OPENSSL s_client -connect $NODEIP:$PORT $BUGS -nextprotoneg $NPN_PROTOs $SNI $ERRFILE >$TMPFILE tmpstr=$(grep -a '^Protocols' $TMPFILE | sed 's/Protocols.*: //') if [[ -z "$tmpstr" ]] || [[ "$tmpstr" == " " ]]; then outln "not offered" @@ -2454,7 +2474,7 @@ run_spdy() { ret=10 fi fi - outln + #outln # btw: nmap can do that too http://nmap.org/nsedoc/scripts/tls-nextprotoneg.html # nmap --script=tls-nextprotoneg #NODE -p $PORT is your friend if your openssl doesn't want to test this tmpfile_handle $FUNCNAME.txt @@ -2462,6 +2482,39 @@ run_spdy() { } +run_http2() { + local tmpstr + local -i ret=0 + + pr_bold " HTTP2/ALPN " + if ! http2_pre ; then + outln "\n" + return 0 + fi + for proto in $ALPN_PROTOs; do + # for some reason OpenSSL doesn't list the advertised protocols, so instead try common protocols + $OPENSSL s_client -connect $NODEIP:$PORT $BUGS -alpn $proto $SNI $ERRFILE >$TMPFILE + tmpstr=$(grep -a '^ALPN protocol' $TMPFILE | sed 's/ALPN protocol.*: //') + if [[ "$tmpstr" = "$proto" ]]; then + if [[ -z "$had_alpn_proto" ]]; then + out "$proto" + had_alpn_proto=1 + else + out ", $proto" + fi + fi + done + if [ "$had_alpn_proto" ]; then + outln " (offered)" + ret=0 + else + outln "not offered" + ret=1 + fi + tmpfile_handle $FUNCNAME.txt + return $ret +} + # arg1: string to send # arg2: possible success strings a egrep pattern, needed! starttls_line() { @@ -4062,6 +4115,7 @@ $PROG_NAME URI ("$PROG_NAME URI" does everything except -E) -S, --server_defaults displays the servers default picks and certificate info -P, --preference displays the servers picks: protocol+cipher -y, --spdy, --npn checks for SPDY/NPN + -Y, --http2, --alpn checks for HTTP2/ALPN -x, --single-cipher tests matched of ciphers (if not a number: word match) -U, --vulnerable tests all vulnerabilities @@ -4925,6 +4979,7 @@ initialize_globals() { do_server_defaults=false do_server_preference=false do_spdy=false + do_http2=false do_ssl_poodle=false do_tls_fallback_scsv=false do_test_just_one=false @@ -4952,6 +5007,7 @@ set_scanning_defaults() { do_server_defaults=true do_server_preference=true do_spdy=true + do_http2=true do_ssl_poodle=true do_tls_fallback_scsv=true VULN_COUNT=10 @@ -4963,7 +5019,7 @@ query_globals() { for gbl in do_allciphers do_vulnerabilities do_beast do_breach do_ccs_injection do_cipher_per_proto do_crime \ do_freak do_logjam do_header do_heartbleed do_mx_all_ips do_pfs do_protocols do_rc4 do_renego \ - do_std_cipherlists do_server_defaults do_server_preference do_spdy do_ssl_poodle do_tls_fallback_scsv \ + do_std_cipherlists do_server_defaults do_server_preference do_spdy do_http2 do_ssl_poodle do_tls_fallback_scsv \ do_test_just_one do_tls_sockets do_mass_testing; do [[ "${!gbl}" == "true" ]] && let true_nr++ done @@ -4976,7 +5032,7 @@ debug_globals() { for gbl in do_allciphers do_vulnerabilities do_beast do_breach do_ccs_injection do_cipher_per_proto do_crime \ do_freak do_logjam do_header do_heartbleed do_rc4 do_mx_all_ips do_pfs do_protocols do_rc4 do_renego \ - do_std_cipherlists do_server_defaults do_server_preference do_spdy do_ssl_poodle do_tls_fallback_scsv \ + do_std_cipherlists do_server_defaults do_server_preference do_spdy do_http2 do_ssl_poodle do_tls_fallback_scsv \ do_test_just_one do_tls_sockets do_mass_testing; do printf "%-22s = %s\n" $gbl "${!gbl}" done @@ -5064,10 +5120,14 @@ parse_cmd_line() { -p|--protocols) do_protocols=true do_spdy=true + do_http2=true ;; -y|--spdy|--npn) do_spdy=true ;; + -Y|--http2|--alpn) + do_http2=true + ;; -f|--ciphers) do_std_cipherlists=true ;; @@ -5302,6 +5362,7 @@ lets_roll() { # all top level functions now following have the prefix "run_" $do_protocols && { run_protocols; ret=$(($? + ret)); } $do_spdy && { run_spdy; ret=$(($? + ret)); } + $do_http2 && { run_http2; ret=$(($? + ret)); } $do_std_cipherlists && { run_std_cipherlists; ret=$(($? + ret)); } $do_pfs && { run_pfs; ret=$(($? + ret)); } $do_server_preference && { run_server_preference; ret=$(($? + ret)); } From 3d28f44e566b94c5d518a9c0321ecec287e6fba4 Mon Sep 17 00:00:00 2001 From: Laine Gholson Date: Sat, 12 Dec 2015 18:41:13 -0600 Subject: [PATCH 2/8] Change flag order --- testssl.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/testssl.sh b/testssl.sh index b05a432..30e41dd 100755 --- a/testssl.sh +++ b/testssl.sh @@ -2458,7 +2458,7 @@ run_spdy() { outln "\n" return 0 fi - $OPENSSL s_client -connect $NODEIP:$PORT $BUGS -nextprotoneg $NPN_PROTOs $SNI $ERRFILE >$TMPFILE + $OPENSSL s_client -connect $NODEIP:$PORT $BUGS $SNI -nextprotoneg $NPN_PROTOs $ERRFILE >$TMPFILE tmpstr=$(grep -a '^Protocols' $TMPFILE | sed 's/Protocols.*: //') if [[ -z "$tmpstr" ]] || [[ "$tmpstr" == " " ]]; then outln "not offered" @@ -2493,7 +2493,7 @@ run_http2() { fi for proto in $ALPN_PROTOs; do # for some reason OpenSSL doesn't list the advertised protocols, so instead try common protocols - $OPENSSL s_client -connect $NODEIP:$PORT $BUGS -alpn $proto $SNI $ERRFILE >$TMPFILE + $OPENSSL s_client -connect $NODEIP:$PORT $BUGS $SNI -alpn $proto $ERRFILE >$TMPFILE tmpstr=$(grep -a '^ALPN protocol' $TMPFILE | sed 's/ALPN protocol.*: //') if [[ "$tmpstr" = "$proto" ]]; then if [[ -z "$had_alpn_proto" ]]; then From e8b04c77d370e90d4e5605bb4bab19d5fdfdc37a Mon Sep 17 00:00:00 2001 From: Laine Gholson Date: Sat, 12 Dec 2015 20:07:24 -0600 Subject: [PATCH 3/8] Consider h2 a valid NPN protocol --- testssl.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testssl.sh b/testssl.sh index 30e41dd..638b6f7 100755 --- a/testssl.sh +++ b/testssl.sh @@ -2465,7 +2465,7 @@ run_spdy() { ret=1 else # now comes a strange thing: "Protocols advertised by server:" is empty but connection succeeded - if echo $tmpstr | egrep -aq "spdy|http" ; then + if echo $tmpstr | egrep -aq "h2|spdy|http" ; then out "$tmpstr" outln " (advertised)" ret=0 From 1bd08f34bd3a64c64a4770113acfe7fd321e3c3b Mon Sep 17 00:00:00 2001 From: Laine Gholson Date: Sat, 12 Dec 2015 22:58:52 -0600 Subject: [PATCH 4/8] Remove redundant newlines --- testssl.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/testssl.sh b/testssl.sh index 638b6f7..1c6c5bd 100755 --- a/testssl.sh +++ b/testssl.sh @@ -2455,7 +2455,7 @@ run_spdy() { pr_bold " SPDY/NPN " if ! spdy_pre ; then - outln "\n" + outln return 0 fi $OPENSSL s_client -connect $NODEIP:$PORT $BUGS $SNI -nextprotoneg $NPN_PROTOs $ERRFILE >$TMPFILE @@ -2488,7 +2488,7 @@ run_http2() { pr_bold " HTTP2/ALPN " if ! http2_pre ; then - outln "\n" + outln return 0 fi for proto in $ALPN_PROTOs; do From f56fdd43daebc1c1506c943ae1eae48cfcf5faee Mon Sep 17 00:00:00 2001 From: Laine Gholson Date: Sat, 12 Dec 2015 23:09:42 -0600 Subject: [PATCH 5/8] Don't output reason not testing spdy when testing server prefs --- testssl.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/testssl.sh b/testssl.sh index 1c6c5bd..fd9599e 100755 --- a/testssl.sh +++ b/testssl.sh @@ -1744,7 +1744,7 @@ run_server_preference() { [[ -n "$PROXY" ]] && arg=" SPDY/NPN is" [[ -n "$STARTTLS" ]] && arg=" " - if spdy_pre " $arg"; then # is NPN/SPDY supported and is this no STARTTLS? / no PROXY + if spdy_pre " $arg" >/dev/null; then # is NPN/SPDY supported and is this no STARTTLS? / no PROXY $OPENSSL s_client -host $NODE -port $PORT $BUGS -nextprotoneg "$NPN_PROTOs" >$ERRFILE >$TMPFILE if sclient_connect_successful $? $TMPFILE; then proto[i]=$(grep -aw "Next protocol" $TMPFILE | sed -e 's/^Next protocol://' -e 's/(.)//' -e 's/ //g') @@ -1755,8 +1755,8 @@ run_server_preference() { [[ $DEBUG -ge 2 ]] && outln "Default cipher for ${proto[i]}: ${cipher[i]}" fi fi - else - outln # we miss for STARTTLS 1x LF otherwise + #else + #outln # we miss for STARTTLS 1x LF otherwise fi for i in 1 2 3 4 5 6; do From d43351e2cbf5e942af17b39cf1008dbc4b894610 Mon Sep 17 00:00:00 2001 From: Laine Gholson Date: Sun, 13 Dec 2015 13:13:17 -0600 Subject: [PATCH 6/8] Undo commit f56fdd4 --- testssl.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/testssl.sh b/testssl.sh index fd9599e..ce789d9 100755 --- a/testssl.sh +++ b/testssl.sh @@ -1744,8 +1744,8 @@ run_server_preference() { [[ -n "$PROXY" ]] && arg=" SPDY/NPN is" [[ -n "$STARTTLS" ]] && arg=" " - if spdy_pre " $arg" >/dev/null; then # is NPN/SPDY supported and is this no STARTTLS? / no PROXY - $OPENSSL s_client -host $NODE -port $PORT $BUGS -nextprotoneg "$NPN_PROTOs" >$ERRFILE >$TMPFILE + if spdy_pre " $arg" ; then # is NPN/SPDY supported and is this no STARTTLS? / no PROXY + $OPENSSL s_client -connect $NODEIP:$PORT $BUGS -nextprotoneg "$NPN_PROTOs" >$ERRFILE >$TMPFILE if sclient_connect_successful $? $TMPFILE; then proto[i]=$(grep -aw "Next protocol" $TMPFILE | sed -e 's/^Next protocol://' -e 's/(.)//' -e 's/ //g') if [[ -z "${proto[i]}" ]]; then @@ -1755,8 +1755,8 @@ run_server_preference() { [[ $DEBUG -ge 2 ]] && outln "Default cipher for ${proto[i]}: ${cipher[i]}" fi fi - #else - #outln # we miss for STARTTLS 1x LF otherwise + else + outln # we miss for STARTTLS 1x LF otherwise fi for i in 1 2 3 4 5 6; do From d0122698edde9fa3cbee8a087f1b3532c6340b21 Mon Sep 17 00:00:00 2001 From: Laine Gholson Date: Sun, 13 Dec 2015 13:16:37 -0600 Subject: [PATCH 7/8] Fix ALPN when testing multiple IPs --- testssl.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/testssl.sh b/testssl.sh index ce789d9..03e8ece 100755 --- a/testssl.sh +++ b/testssl.sh @@ -2485,6 +2485,7 @@ run_spdy() { run_http2() { local tmpstr local -i ret=0 + local had_alpn_proto pr_bold " HTTP2/ALPN " if ! http2_pre ; then From d2df8b859024cd9e4a3dc20d4292a16c1268952b Mon Sep 17 00:00:00 2001 From: Laine Gholson Date: Mon, 21 Dec 2015 10:37:23 -0600 Subject: [PATCH 8/8] Fix unrelated typos --- testssl.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/testssl.sh b/testssl.sh index 03e8ece..f6bc2ce 100755 --- a/testssl.sh +++ b/testssl.sh @@ -133,7 +133,7 @@ DEBUG=${DEBUG:-0} # 1.: the temp files won't be erased. # 3: slight hexdumps + other info, # 4: display bytes sent via sockets, 5: display bytes received via sockets, 6: whole 9 yards WIDE=${WIDE:-false} # whether to display for some options the cipher or the table with hexcode/KX,Enc,strength etc. -LOGFILE=${LOGILE-""} # logfile if used +LOGFILE=${LOGFILE:-""} # logfile if used HAS_IPv6=${HAS_IPv6:-false} # if you have OPENSSL with IPv6 support AND IPv6 networking set it to yes and testssl.sh works! # tuning vars, can not be set by a cmd line switch @@ -220,7 +220,7 @@ readonly UA_SNEAKY="Mozilla/5.0 (X11; Linux x86_64; rv:41.0) Gecko/20100101 Fire TLS_LOW_BYTE="" HEX_CIPHER="" - # The various hexdump commands we need to replace xxd (BSD compatibility)) + # The various hexdump commands we need to replace xxd (BSD compatibility) HEXDUMPVIEW=(hexdump -C) # This is used in verbose mode to see what's going on HEXDUMP=(hexdump -ve '16/1 "%02x " " \n"') # This is used to analyze the reply HEXDUMPPLAIN=(hexdump -ve '1/1 "%.2x"') # Replaces both xxd -p and tr -cd '[:print:]'