From 966f414a2ba52f34cd631303e319d1eab2704f5a Mon Sep 17 00:00:00 2001 From: Dirk Wetter Date: Thu, 24 Jan 2019 17:57:29 +0100 Subject: [PATCH] Multiple IP scan fix (no --file) + single cipher scan works with multiple IPs This PR addresses the problem (#1037) that if a hostname resolves to multiple IP addresses only the first one is being scanned as this IP isn't reachable and the scan terminated here and didn't continue with the 2nd, 3rd etc. Same applied to scans with --mx. This based on the global MULTIPLE_CHECKS which is set to true whenever such a scan is started. One minor point: Also if the last IP isn't reachable the output will say "proceeding with next:". I guess that should be clear looking at the (different outputs). This PR also fixes a scan problem with a single cipher/pattern (-x/--single-cipher): previously where only one IP was scanned. Furthermore some redundant quotes were removed. --- testssl.sh | 262 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 147 insertions(+), 115 deletions(-) diff --git a/testssl.sh b/testssl.sh index bd74d77..69bcea0 100755 --- a/testssl.sh +++ b/testssl.sh @@ -158,7 +158,7 @@ HAS_OPENBSDDATE=false if date -d @735275209 >/dev/null 2>&1; then if date -r @735275209 >/dev/null 2>&1; then # it can't do any conversion from a plain date output - HAS_OPENBSDDATE=true + HAS_OPENBSDDATE=true else HAS_GNUDATE=true fi @@ -277,6 +277,7 @@ HTMLHEADER=true # same for HTML SECTION_FOOTER_NEEDED=false # kludge for tracking whether we need to close the JSON section object GIVE_HINTS=false # give an additional info to findings SERVER_SIZE_LIMIT_BUG=false # Some servers have either a ClientHello total size limit or a 128 cipher limit (e.g. old ASAs) +MULTIPLE_CHECKS=false # need to know whether an MX record or a hostname resolves to multiple IPs to check CHILD_MASS_TESTING=${CHILD_MASS_TESTING:-false} HAD_SLEPT=0 NR_SOCKET_FAIL=0 # Counter for socket failures @@ -1937,7 +1938,7 @@ service_detection() { # connectivity_problem() { if [[ $1 -lt $2 ]]; then - prln_warning "Oops: $3" + prln_warning " Oops: $3" return 0 fi if [[ $1 -ge $2 ]]; then @@ -3241,7 +3242,7 @@ neat_list(){ [[ "$DISPLAY_CIPHERNAMES" != openssl-only ]] && tls_cipher="$(show_rfc_style "$hexcode")" - if [[ "$5" != "true" ]]; then + if [[ "$5" != true ]]; then if [[ "$DISPLAY_CIPHERNAMES" =~ rfc ]]; then line="$(printf -- " %-7s %-49s %-10s %-12s%-8s" "$hexcode" "$tls_cipher" "$kx" "$enc" "$strength")" [[ "$DISPLAY_CIPHERNAMES" != rfc-only ]] && line+="$(printf -- " %-33s${SHOW_EACH_C:+ %-0s}" "$ossl_cipher")" @@ -3601,15 +3602,6 @@ run_cipher_match(){ done "$using_sockets" && HAS_DH_BITS="$has_dh_bits" tmpfile_handle ${FUNCNAME[0]}.txt - stopwatch run_cipher_match - fileout_section_footer true - outln - calc_scantime - datebanner " Done" - - "$MEASURE_TIME" && printf "%${COLUMNS}s\n" "$SCAN_TIME" - [[ -e "$MEASURE_TIME_FILE" ]] && echo "Total : $SCAN_TIME " >> "$MEASURE_TIME_FILE" - exit done outln @@ -9438,6 +9430,9 @@ fd_socket() { imap|imaps) # IMAP, https://tools.ietf.org/html/rfc2595, https://tools.ietf.org/html/rfc3501 starttls_imap_dialog ;; + irc|ircs) # IRC, https://ircv3.net/specs/extensions/tls-3.1.html, https://ircv3.net/specs/core/capability-negotiation.html + fatal "FIXME: IRC+STARTTLS not yet supported" $ERR_NOSUPPORT + ;; ldap|ldaps) # LDAP, https://tools.ietf.org/html/rfc2830, https://tools.ietf.org/html/rfc4511 fatal "FIXME: LDAP+STARTTLS over sockets not yet supported (try \"--ssl-native\")" $ERR_NOSUPPORT ;; @@ -9459,7 +9454,7 @@ fd_socket() { esac fi [[ $? -eq 0 ]] && return 0 - prln_warning "STARTTLS handshake failed" + prln_warning " STARTTLS handshake failed" return 1 } @@ -16246,9 +16241,11 @@ child_error() { exit $ERR_CHILD } + +# Program terminates prematurely, with error code # arg1: string to print / to write to file -# arg2: error code, is a global, see ERR_* above -# arg3: an optional string +# arg2: global error code, see ERR_* above +# arg3: an optional hint (string) # fatal() { outln @@ -16262,6 +16259,18 @@ fatal() { exit $2 } +# This OTOH doesn't exit but puts a fatal error to the screen but continues with the next +# IP/hostname. It should only be used if a single IP/Hostname in a scan is not reachable. +# arg1: string to print / to write to file +# +ip_fatal() { + outln + prln_magenta "Fatal error: $1, proceeding with next IP (if any)" >&2 + [[ -n "$LOGFILE" ]] && prln_magenta "Fatal error: $1, proceeding with next IP (if any)" >>$LOGFILE + outln + fileout "scanProblem" "FATAL" "$1, proceeding with next IP (if any)" + return 0 +} initialize_engine(){ # for now only GOST engine @@ -16895,21 +16904,26 @@ determine_optimal_proto() { } -# arg1: ftp smtp, lmtp, pop3, imap, xmpp, telnet, ldap, postgres, mysql (maybe with trailing s) +# arg1: ftp smtp, lmtp, pop3, imap, xmpp, telnet, ldap, postgres, mysql, irc, nntp (maybe with trailing s) determine_service() { local ua - local protocol + local protocol error_msg - if ! fd_socket 5; then # check if we can connect to $NODEIP:$PORT + # check if we can connect to $NODEIP:$PORT + if ! fd_socket 5; then if [[ -n "$PROXY" ]]; then fatal "You're sure $PROXYNODE:$PROXYPORT allows tunneling here? Can't connect to \"$NODEIP:$PORT\"" $ERR_CONNECT else - fatal "Can't connect to \"$NODEIP:$PORT\"\nMake sure a firewall is not between you and your scanning target!" $ERR_CONNECT + if "$MULTIPLE_CHECKS"; then + ip_fatal "Couldn't connect to $NODEIP:$PORT" + return 1 + else + fatal "Can't connect to \"$NODEIP:$PORT\"\nMake sure a firewall is not between you and your scanning target!" $ERR_CONNECT + fi fi fi close_socket - datebanner " Start" outln if [[ -z "$1" ]]; then # no STARTTLS. @@ -16926,6 +16940,7 @@ determine_service() { else protocol=${1%s} # strip trailing 's' in ftp(s), smtp(s), pop3(s), etc fi + case "$protocol" in ftp|smtp|lmtp|pop3|imap|xmpp|telnet|ldap|postgres|mysql|nntp) STARTTLS="-starttls $protocol" @@ -16973,12 +16988,20 @@ determine_service() { fatal "Your $OPENSSL does not support the \"-starttls nntp\" option" $ERR_OSSLBIN fi fi + $OPENSSL s_client $(s_client_options "-connect $NODEIP:$PORT $PROXY $BUGS $STARTTLS") 2>$ERRFILE >$TMPFILE