From 8dbaab36569f9faf98e25d1b7cd5121521a234f9 Mon Sep 17 00:00:00 2001 From: Dirk Wetter Date: Sat, 7 Mar 2020 15:40:19 +0100 Subject: [PATCH] Socksend modernize part 3, with a PoC for #1535: DONT USE THIS OTHERWISE This moves the run_ticketbleed function to the socketsend_clienthello. It is not working yet, see also #1535 why. This is just for the PoC, I'll explain: It has now a function named check_bytestream() which will be called in debug mode 1 and checks whether the byte stream to be send via bash sockets is properly formatted. It can detect bugs which otherwise would be hard to discover. DO NOT USE IT for anything else than the check ---snip: code: check_bytestream() { local line="" local -i i=0 # We do a search and replace so that \xaa\x29 becomes # _xaa # _x29 # # "echo -e" helps us to get a multiline string while read -r line; do if [[ $i -eq 0 ]]; then # first line is empty because this is a LF : elif [[ ${#line} -ne 4 ]] && [[ $i != 0 ]]; then echo "length of byte $i called from $2 is not ok" elif [[ ${line:0:1} != _ ]]; then echo "char $i called from $2 doesn't start with a \"\\\"" elif [[ ${line:1:1} != x ]]; then echo "char $i called from $2 doesn't have an x in second position" elif [[ ${line:2:2} != [0-9a-fA-F][0-9a-fA-F] ]]; then echo "byte $i called from $2 is not hex" fi i+=1 done < <( echo -e ${1//\\/\\n_}) } socksend_clienthello() { local data="" code2network "$1" data="$NW_STR" if [[ "$DEBUG" -ge 1 ]]; then check_bytestream "$data" "${FUNCNAME[1]}" [[ "$DEBUG" -ge 4 ]] && echo && echo "\"$data\"" [..] Result (./testssl.sh -q --debug=1 -U dev.testssl.sh): Testing vulnerabilities Heartbleed (CVE-2014-0160) not vulnerable (OK), no heartbeat extension CCS (CVE-2014-0224) not vulnerable (OK) Ticketbleed (CVE-2016-9244), experiment. length of byte 311 called from run_ticketbleed is not ok length of byte 312 called from run_ticketbleed is not ok length of byte 313 called from run_ticketbleed is not ok length of byte 314 called from run_ticketbleed is not ok length of byte 315 called from run_ticketbleed is not ok length of byte 316 called from run_ticketbleed is not ok length of byte 317 called from run_ticketbleed is not ok [..] ---snap Besides that: * dec02hex was corrected (only being used for run_ticketbleed) * dec04hex is still buggy and part of the problem * some quotes removed from rhs of [[]] --- testssl.sh | 189 ++++++++++++++++++++++++++++++++--------------------- 1 file changed, 113 insertions(+), 76 deletions(-) diff --git a/testssl.sh b/testssl.sh index 40322fb..6242292 100755 --- a/testssl.sh +++ b/testssl.sh @@ -747,8 +747,9 @@ debugme() { return 0 } -hex2dec() { - echo $((16#$1)) +debugme1() { + [[ "$DEBUG" -ge 1 ]] && "$@" + return 0 } # convert 414243 into ABC @@ -760,15 +761,20 @@ hex2ascii() { done } +hex2dec() { + echo $((16#$1)) +} + + # convert decimal number < 256 to hex dec02hex() { - printf "x%02x" "$1" + printf "%02x" "$1" } # convert decimal number between 256 and < 256*256 to hex dec04hex() { local a=$(printf "%04x" "$1") - printf "x%02s, x%02s" "${a:0:2}" "${a:2:2}" + printf "%02s, %02s" "${a:0:2}" "${a:2:2}" } @@ -10476,6 +10482,34 @@ code2network() { done <<< "$1")" } +# arg1: formatted bytesstream to be send +# arg2: caller function +check_bytestream() { + local line="" + local -i i=0 + + # We do a search and replace so that \xaa\x29 becomes + # _xaa + # _x29 + # + # "echo -e" helps us to get a multiline string + while read -r line; do + if [[ $i -eq 0 ]]; then + # first line is empty because this is a LF + : + elif [[ ${#line} -ne 4 ]] && [[ $i != 0 ]]; then + echo "length of byte $i called from $2 is not ok" + elif [[ ${line:0:1} != _ ]]; then + echo "char $i called from $2 doesn't start with a \"\\\"" + elif [[ ${line:1:1} != x ]]; then + echo "char $i called from $2 doesn't have an x in second position" + elif [[ ${line:2:2} != [0-9a-fA-F][0-9a-fA-F] ]]; then + echo "byte $i called from $2 is not hex" + fi + i+=1 + done < <( echo -e ${1//\\/\\n_}) +} + # sockets inspired by http://blog.chris007.de/?p=238 # ARG1: hexbytes separated by commas, with a leading comma # ARG2: seconds to sleep @@ -10484,7 +10518,10 @@ socksend_clienthello() { code2network "$1" data="$NW_STR" - [[ "$DEBUG" -ge 4 ]] && echo && echo "\"$data\"" + if [[ "$DEBUG" -ge 1 ]]; then + check_bytestream "$data" "${FUNCNAME[1]}" + [[ "$DEBUG" -ge 4 ]] && echo && echo "\"$data\"" + fi if [[ -z "$PRINTF" ]] ;then # We could also use "dd ibs=1M obs=1M" here but is seems to be at max 3% slower printf -- "$data" | cat >&5 2>/dev/null & @@ -10501,7 +10538,6 @@ socksend_clienthello() { socksend() { local data line - # read line per line and strip comments (bash internal func can't handle multiline statements data="$(while read line; do printf "${line%%\#*}" done <<< "$1" )" @@ -14880,7 +14916,7 @@ receive_app_data() { # mainly adapted from https://gist.github.com/takeshixx/10107280 # run_heartbleed(){ - local tls_hexcode + local tls_hexcode tls_proto local heartbleed_payload local -i n lines_returned local append="" @@ -14925,8 +14961,8 @@ run_heartbleed(){ fi debugme echo "using protocol $tls_hexcode" - # attention, this is dangerous as it relies on spaces etc. above - tls_sockets "${tls_hexcode:4:2}" "" "ephemeralkey" "" "" "false" + tls_proto="${tls_hexcode:4:2}" + tls_sockets "${tls_proto}" "" "ephemeralkey" "" "" "false" [[ $DEBUG -ge 4 ]] && tmln_out "\nsending payload with TLS version $tls_hexcode:" heartbleed_payload=", 18, $tls_hexcode, 00, 03, 01, 40,00" @@ -15187,8 +15223,8 @@ sub_session_ticket_tls() { run_ticketbleed() { local session_tckt_tls="" local -i len_ch=300 # fixed len of prepared clienthello below - local sid="x00,x0B,xAD,xC0,xDE,x00," # some abitratry bytes - local len_sid="$(( ${#sid} / 4))" + local sid="00,0B,AD,C0,DE,00," # some abitratry bytes + local len_sid="$(( ${#sid} / 3))" local xlen_sid="$(dec02hex $len_sid)" local -i len_tckt_tls=0 nr_sid_detected=0 local xlen_tckt_tls="" xlen_handshake_record_layer="" xlen_handshake_ssl_layer="" @@ -15214,7 +15250,7 @@ run_ticketbleed() { # highly unlikely that it is NOT supported. We may loose time here but it's more solid [[ -z "$TLS_EXTENSIONS" ]] && determine_tls_extensions - if [[ ! "${TLS_EXTENSIONS}" =~ "session ticket" ]]; then + if [[ ! "${TLS_EXTENSIONS}" =~ session\ ticket ]]; then pr_svrty_best "not vulnerable (OK)" outln ", no session ticket extension" fileout "$jsonID" "OK" "no session ticket extension" "$cve" "$cwe" @@ -15222,26 +15258,26 @@ run_ticketbleed() { fi if [[ 0 -eq $(has_server_protocol tls1) ]]; then - tls_hexcode="x03, x01" + tls_hexcode="03,01" elif [[ 0 -eq $(has_server_protocol tls1_1) ]]; then - tls_hexcode="x03, x02" + tls_hexcode="03,02" elif [[ 0 -eq $(has_server_protocol tls1_2) ]]; then - tls_hexcode="x03, x03" + tls_hexcode="03,03" elif [[ 0 -eq $(has_server_protocol ssl3) ]]; then - tls_hexcode="x03, x00" + tls_hexcode="03,00" else # no protocol for some reason defined, determine TLS versions offered with a new handshake $OPENSSL s_client $(s_client_options "$STARTTLS $BUGS -connect $NODEIP:$PORT $PROXY") >$TMPFILE 2>$ERRFILE