mirror of
				https://github.com/drwetter/testssl.sh.git
				synced 2025-11-03 23:35:26 +01:00 
			
		
		
		
	Merge pull request #503 from AlGreed/2.9dev
new pretty JSON format + severity level filter
This commit is contained in:
		
							
								
								
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -1,3 +1,7 @@
 | 
			
		||||
.DS_Store
 | 
			
		||||
tmp.json
 | 
			
		||||
*.bak
 | 
			
		||||
 | 
			
		||||
*.xml
 | 
			
		||||
 | 
			
		||||
*.iml
 | 
			
		||||
 
 | 
			
		||||
@@ -28,7 +28,7 @@ foreach my $f ( @$json ) {
 | 
			
		||||
	if ( $f->{id} eq "expiration" ) {
 | 
			
		||||
		$found = 1;
 | 
			
		||||
		like($f->{finding},qr/^Certificate Expiration.*expired\!/,"Finding reads expired."); $tests++;
 | 
			
		||||
		is($f->{severity}, "NOT ok", "Severity should be NOT ok"); $tests++;
 | 
			
		||||
		is($f->{severity}, "CRITICAL", "Severity should be CRITICAL"); $tests++;
 | 
			
		||||
		last;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -56,7 +56,7 @@ foreach my $f ( @$json ) {
 | 
			
		||||
	if ( $f->{id} eq "chain_of_trust" ) {
 | 
			
		||||
	$found = 1;
 | 
			
		||||
		like($f->{finding},qr/^All certificate trust checks failed/,"Finding says certificate cannot be trusted."); $tests++;
 | 
			
		||||
		is($f->{severity}, "NOT ok", "Severity should be NOT ok"); $tests++;
 | 
			
		||||
		is($f->{severity}, "CRITICAL", "Severity should be CRITICAL"); $tests++;
 | 
			
		||||
		last;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -100,7 +100,7 @@ foreach my $f ( @$json ) {
 | 
			
		||||
	if ( $f->{id} eq "chain_of_trust" ) {
 | 
			
		||||
		$found = 1;
 | 
			
		||||
		like($f->{finding},qr/^All certificate trust checks failed.*incomplete/,"Finding says certificate cannot be trusted."); $tests++;
 | 
			
		||||
		is($f->{severity}, "NOT ok", "Severity should be NOT ok"); $tests++;
 | 
			
		||||
		is($f->{severity}, "CRITICAL", "Severity should be CRITICAL"); $tests++;
 | 
			
		||||
		last;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -118,7 +118,7 @@ is($found,1,"We had a finding for this in the JSON output"); $tests++;
 | 
			
		||||
#	if ( $f->{id} eq "chain_of_trust" ) {
 | 
			
		||||
#		$found = 1;
 | 
			
		||||
#		like($f->{finding},qr/^All certificate trust checks failed.*incomplete/,"Finding says certificate cannot be trusted."); $tests++;
 | 
			
		||||
#		is($f->{severity}, "NOT ok", "Severity should be NOT ok"); $tests++;
 | 
			
		||||
#		is($f->{severity}, "CRITICAL", "Severity should be CRITICAL"); $tests++;
 | 
			
		||||
#		last;
 | 
			
		||||
#    }
 | 
			
		||||
#}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										344
									
								
								testssl.sh
									
									
									
									
									
								
							
							
						
						
									
										344
									
								
								testssl.sh
									
									
									
									
									
								
							@@ -255,6 +255,8 @@ GET_REQ11=""
 | 
			
		||||
readonly UA_STD="TLS tester from $SWURL"
 | 
			
		||||
readonly UA_SNEAKY="Mozilla/5.0 (X11; Linux x86_64; rv:41.0) Gecko/20100101 Firefox/41.0"
 | 
			
		||||
FIRST_FINDING=true                      # Is this the first finding we are outputting to file?
 | 
			
		||||
START_TIME=0
 | 
			
		||||
END_TIME=0
 | 
			
		||||
 | 
			
		||||
# Devel stuff, see -q below
 | 
			
		||||
TLS_LOW_BYTE=""
 | 
			
		||||
@@ -264,6 +266,45 @@ HEX_CIPHER=""
 | 
			
		||||
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:]'
 | 
			
		||||
 | 
			
		||||
#################### SEVERITY ####################
 | 
			
		||||
INFO=0
 | 
			
		||||
OK=0
 | 
			
		||||
LOW=1
 | 
			
		||||
MEDIUM=2
 | 
			
		||||
HIGH=3
 | 
			
		||||
CRITICAL=4
 | 
			
		||||
 | 
			
		||||
SEVERITY_LEVEL=0
 | 
			
		||||
 | 
			
		||||
set_severity_level() {
 | 
			
		||||
   local severity=$1
 | 
			
		||||
 | 
			
		||||
   if [[ "$severity" == "LOW" ]]; then
 | 
			
		||||
           SEVERITY_LEVEL=$LOW
 | 
			
		||||
   elif [[ "$severity" == "MEDIUM" ]]; then
 | 
			
		||||
           SEVERITY_LEVEL=$MEDIUM
 | 
			
		||||
   elif [[ "$severity" == "HIGH" ]]; then
 | 
			
		||||
           SEVERITY_LEVEL=$HIGH
 | 
			
		||||
   elif [[ "$severity" == "CRITICAL" ]]; then
 | 
			
		||||
           SEVERITY_LEVEL=$CRITICAL
 | 
			
		||||
   else
 | 
			
		||||
        echo "Supported severity levels are LOW, MEDIUM, HIGH, CRITICAL!"
 | 
			
		||||
        help
 | 
			
		||||
   fi
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
show_finding() {
 | 
			
		||||
   local severity=$1
 | 
			
		||||
 | 
			
		||||
   ([[ "$severity" == "DEBUG" ]]) ||
 | 
			
		||||
   ([[ "$severity" == "WARN" ]]) ||
 | 
			
		||||
   ([[ "$severity" == "INFO" ]] && [[ $SEVERITY_LEVEL -le $INFO ]]) ||
 | 
			
		||||
   ([[ "$severity" == "OK" ]] && [[ $SEVERITY_LEVEL -le $OK ]]) ||
 | 
			
		||||
   ([[ "$severity" == "LOW" ]] && [[ $SEVERITY_LEVEL -le $LOW ]]) ||
 | 
			
		||||
   ([[ "$severity" == "MEDIUM" ]] && [[ $SEVERITY_LEVEL -le $MEDIUM ]]) ||
 | 
			
		||||
   ([[ "$severity" == "HIGH" ]] && [[ $SEVERITY_LEVEL -le $HIGH ]]) ||
 | 
			
		||||
   ([[ "$severity" == "CRITICAL" ]] && [[ $SEVERITY_LEVEL -le $CRITICAL ]])
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
###### some hexbytes for bash network sockets follow ######
 | 
			
		||||
@@ -460,12 +501,117 @@ strip_quote() {
 | 
			
		||||
          -e 's/ *$//g' <<< "$1"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#################### JSON FILE FORMATING ####################
 | 
			
		||||
fileout_pretty_json_header() {
 | 
			
		||||
    START_TIME=$(date +%s)
 | 
			
		||||
 | 
			
		||||
    echo -e "          \"host\"        : \"$NODE\",
 | 
			
		||||
          \"port\"        : \"$PORT\",
 | 
			
		||||
          \"startTime\"   : \"$START_TIME\",
 | 
			
		||||
          \"version\"     : \"$VERSION\",
 | 
			
		||||
          \"scanResult\"  : {
 | 
			
		||||
          "
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fileout_pretty_json_footer() {
 | 
			
		||||
    local scan_time=$((END_TIME - START_TIME))
 | 
			
		||||
    echo -e "          },
 | 
			
		||||
          \"ip\"        : \"$NODEIP\",
 | 
			
		||||
          \"scanTime\"  : \"$scan_time\"\n}"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fileout_json_header() {
 | 
			
		||||
     "$do_json" && printf "[\n" > "$JSONFILE"
 | 
			
		||||
     "$do_pretty_json" && (printf "{\n%s" "$(fileout_pretty_json_header)") > "$JSONFILE"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fileout_json_footer() {
 | 
			
		||||
     "$do_json" && printf "]\n" >> "$JSONFILE"
 | 
			
		||||
     "$do_pretty_json" && (printf "\n%s" "$(fileout_pretty_json_footer)") >> "$JSONFILE"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fileout_json_section() {
 | 
			
		||||
    case $1 in
 | 
			
		||||
    1)
 | 
			
		||||
        echo -e "          \"service\"           : ["
 | 
			
		||||
        ;;
 | 
			
		||||
    2)
 | 
			
		||||
        echo -e ",\n                    \"protocols\"         : ["
 | 
			
		||||
        ;;
 | 
			
		||||
    3)
 | 
			
		||||
        echo -e ",\n                    \"ciphers\"           : ["
 | 
			
		||||
        ;;
 | 
			
		||||
    4)
 | 
			
		||||
        echo -e ",\n                    \"pfs\"               : ["
 | 
			
		||||
        ;;
 | 
			
		||||
    5)
 | 
			
		||||
        echo -e ",\n                    \"serverPreferences\" : ["
 | 
			
		||||
        ;;
 | 
			
		||||
    6)
 | 
			
		||||
        echo -e ",\n                    \"serverDefaults\"    : ["
 | 
			
		||||
        ;;
 | 
			
		||||
    7)
 | 
			
		||||
        echo -e ",\n                    \"headerResponse\"    : ["
 | 
			
		||||
        ;;
 | 
			
		||||
    8)
 | 
			
		||||
        echo -e ",\n                    \"vulnerabilities\"   : ["
 | 
			
		||||
        ;;
 | 
			
		||||
    9)
 | 
			
		||||
        echo -e ",\n                    \"cipherTests\"       : ["
 | 
			
		||||
        ;;
 | 
			
		||||
    10)
 | 
			
		||||
        echo -e ",\n                    \"browserSimulations\": ["
 | 
			
		||||
        ;;
 | 
			
		||||
    *)
 | 
			
		||||
        echo "invalid section"
 | 
			
		||||
        ;;
 | 
			
		||||
    esac
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fileout_section_header(){
 | 
			
		||||
    local str=""
 | 
			
		||||
    $2 && str="$(fileout_section_footer)"
 | 
			
		||||
    "$do_pretty_json" && FIRST_FINDING=true && (printf "%s%s\n" "$str" "$(fileout_json_section "$1")") >> "$JSONFILE"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fileout_section_footer() {
 | 
			
		||||
    "$do_pretty_json" && printf "\n                    ]" >> "$JSONFILE"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fileout_json_finding() {
 | 
			
		||||
    if "$do_json"; then
 | 
			
		||||
              "$FIRST_FINDING" || echo -n "," >> "$JSONFILE"
 | 
			
		||||
              echo -e "        {
 | 
			
		||||
              \"id\"           : \"$1\",
 | 
			
		||||
              \"ip\"           : \"$NODE/$NODEIP\",
 | 
			
		||||
              \"port\"         : \"$PORT\",
 | 
			
		||||
              \"severity\"     : \"$2\",
 | 
			
		||||
              \"finding\"      : \"$finding\"
 | 
			
		||||
         }" >> "$JSONFILE"
 | 
			
		||||
    fi
 | 
			
		||||
    if "$do_pretty_json"; then
 | 
			
		||||
         ("$FIRST_FINDING" && echo -n "                            {" >> "$JSONFILE") || echo -n ",{" >> "$JSONFILE"
 | 
			
		||||
         echo -e -n "
 | 
			
		||||
                                \"id\"           : \"$1\",
 | 
			
		||||
                                \"severity\"     : \"$2\",
 | 
			
		||||
                                \"finding\"      : \"$finding\"
 | 
			
		||||
                           }" >> "$JSONFILE"
 | 
			
		||||
    fi
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
is_json_format() {
 | 
			
		||||
    ([[ -f "$JSONFILE" ]] && ("$do_json" || "$do_pretty_json"))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
################# JSON FILE FORMATING END ####################
 | 
			
		||||
 | 
			
		||||
##################### FILE FORMATING #########################
 | 
			
		||||
fileout_header() {
 | 
			
		||||
     if "$APPEND"; then
 | 
			
		||||
          if [[ -f "$JSONFILE" ]]; then
 | 
			
		||||
               FIRST_FINDING=false # We need to insert a comma, because there is file content already
 | 
			
		||||
          else
 | 
			
		||||
               "$do_json" && printf "[\n" > "$JSONFILE"
 | 
			
		||||
               fileout_json_header
 | 
			
		||||
          fi
 | 
			
		||||
          if "$do_csv"; then
 | 
			
		||||
               if [[ -f "$CSVFILE" ]]; then
 | 
			
		||||
@@ -477,34 +623,31 @@ fileout_header() {
 | 
			
		||||
               fi
 | 
			
		||||
          fi
 | 
			
		||||
     else
 | 
			
		||||
          "$do_json" && printf "[\n" > "$JSONFILE"
 | 
			
		||||
          fileout_json_header
 | 
			
		||||
          "$do_csv" && echo "\"id\",\"fqdn/ip\",\"port\",\"severity\",\"finding\"" > "$CSVFILE"
 | 
			
		||||
     fi
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fileout_footer() {
 | 
			
		||||
     "$do_json" && [[ -f "$JSONFILE" ]] && printf "]\n" >> "$JSONFILE"
 | 
			
		||||
     is_json_format && fileout_json_footer
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fileout() { # ID, SEVERITY, FINDING
 | 
			
		||||
     local severity="$2"
 | 
			
		||||
 | 
			
		||||
     if show_finding "$severity"; then
 | 
			
		||||
         local finding=$(strip_lf "$(newline_to_spaces "$(strip_quote "$3")")")
 | 
			
		||||
 | 
			
		||||
     if "$do_json"; then
 | 
			
		||||
          "$FIRST_FINDING" || echo -n "," >> $JSONFILE
 | 
			
		||||
          echo "         {
 | 
			
		||||
               \"id\"           : \"$1\",
 | 
			
		||||
               \"ip\"           : \"$NODE/$NODEIP\",
 | 
			
		||||
               \"port\"         : \"$PORT\",
 | 
			
		||||
               \"severity\"     : \"$2\",
 | 
			
		||||
               \"finding\"      : \"$finding\"
 | 
			
		||||
          }" >> $JSONFILE
 | 
			
		||||
     fi
 | 
			
		||||
         is_json_format && (fileout_json_finding "$1" "$severity" "$finding")
 | 
			
		||||
 | 
			
		||||
         # does the following do any sanitization?
 | 
			
		||||
         if "$do_csv"; then
 | 
			
		||||
          echo -e \""$1\"",\"$NODE/$NODEIP\",\"$PORT"\",\""$2"\",\""$finding"\"" >>$CSVFILE
 | 
			
		||||
              echo -e \""$1\"",\"$NODE/$NODEIP\",\"$PORT"\",\""$severity"\",\""$finding"\"" >> "$CSVFILE"
 | 
			
		||||
         fi
 | 
			
		||||
         "$FIRST_FINDING" && FIRST_FINDING=false
 | 
			
		||||
     fi
 | 
			
		||||
}
 | 
			
		||||
################### FILE FORMATING END #########################
 | 
			
		||||
 | 
			
		||||
###### helper function definitions ######
 | 
			
		||||
 | 
			
		||||
@@ -809,7 +952,7 @@ run_http_header() {
 | 
			
		||||
               out ", redirecting to \"$redirect\""
 | 
			
		||||
               if [[ $redirect == "http://"* ]]; then
 | 
			
		||||
                    pr_svrty_high " -- Redirect to insecure URL (NOT ok)"
 | 
			
		||||
                    fileout "HTTP_STATUS_CODE" "NOT ok" \, "Redirect to insecure URL (NOT ok). Url: \"$redirect\""
 | 
			
		||||
                    fileout "HTTP_STATUS_CODE" "HIGH" \, "Redirect to insecure URL (NOT ok). Url: \"$redirect\""
 | 
			
		||||
               fi
 | 
			
		||||
               fileout "HTTP_STATUS_CODE" "INFO" \
 | 
			
		||||
                    "Testing HTTP header response @ \"$URL_PATH\", $HTTP_STATUS_CODE$msg_thereafter, redirecting to \"$redirect\""
 | 
			
		||||
@@ -893,7 +1036,7 @@ detect_ipv4() {
 | 
			
		||||
                    fi
 | 
			
		||||
                    pr_svrty_high "$result"
 | 
			
		||||
                    outln "\n$spaces$your_ip_msg"
 | 
			
		||||
                    fileout "ip_in_header_$count" "NOT ok" "IPv4 address in header  $result $your_ip_msg"
 | 
			
		||||
                    fileout "ip_in_header_$count" "HIGH" "IPv4 address in header  $result $your_ip_msg"
 | 
			
		||||
               fi
 | 
			
		||||
               count=$count+1
 | 
			
		||||
          done < $HEADERFILE
 | 
			
		||||
@@ -1033,7 +1176,7 @@ run_hsts() {
 | 
			
		||||
          fi
 | 
			
		||||
     else
 | 
			
		||||
          out "--"
 | 
			
		||||
          fileout "hsts" "NOT ok" "No support for HTTP Strict Transport Security"
 | 
			
		||||
          fileout "hsts" "HIGH" "No support for HTTP Strict Transport Security"
 | 
			
		||||
     fi
 | 
			
		||||
     outln
 | 
			
		||||
 | 
			
		||||
@@ -1637,7 +1780,7 @@ std_cipherlists() {
 | 
			
		||||
               1) # the ugly ones
 | 
			
		||||
                    if [[ $sclient_success -eq 0 ]]; then
 | 
			
		||||
                         pr_svrty_critical "offered (NOT ok)"
 | 
			
		||||
                         fileout "std_$4" "NOT ok" "$2 offered (NOT ok) - ugly"
 | 
			
		||||
                         fileout "std_$4" "CRITICAL" "$2 offered (NOT ok) - ugly"
 | 
			
		||||
                    else
 | 
			
		||||
                         pr_done_best "not offered (OK)"
 | 
			
		||||
                         fileout "std_$4" "OK" "$2 not offered (OK)"
 | 
			
		||||
@@ -1646,7 +1789,7 @@ std_cipherlists() {
 | 
			
		||||
               2)   # bad but not worst
 | 
			
		||||
                    if [[ $sclient_success -eq 0 ]]; then
 | 
			
		||||
                         pr_svrty_high "offered (NOT ok)"
 | 
			
		||||
                         fileout "std_$4" "NOT ok" "$2 offered (NOT ok) - bad"
 | 
			
		||||
                         fileout "std_$4" "HIGH" "$2 offered (NOT ok) - bad"
 | 
			
		||||
                    else
 | 
			
		||||
                         pr_done_good "not offered (OK)"
 | 
			
		||||
                         fileout "std_$4" "OK" "$2 not offered (OK)"
 | 
			
		||||
@@ -3202,11 +3345,11 @@ run_protocols() {
 | 
			
		||||
                         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"
 | 
			
		||||
                              fileout "sslv2" "HIGH" "SSLv2 offered (NOT ok), vulnerable to CVE-2015-3197"
 | 
			
		||||
                         else
 | 
			
		||||
                              pr_svrty_critical "offered (NOT ok), also VULNERABLE to DROWN attack";
 | 
			
		||||
                              outln " -- $nr_ciphers_detected ciphers"
 | 
			
		||||
                              fileout "sslv2" "NOT ok" "SSLv2 offered (NOT ok), vulnerable to DROWN attack.  Detected ciphers: $nr_ciphers_detected"
 | 
			
		||||
                              fileout "sslv2" "CRITICAL" "SSLv2 offered (NOT ok), vulnerable to DROWN attack.  Detected ciphers: $nr_ciphers_detected"
 | 
			
		||||
                         fi
 | 
			
		||||
                    fi ;;
 | 
			
		||||
          esac
 | 
			
		||||
@@ -3216,7 +3359,7 @@ run_protocols() {
 | 
			
		||||
          case $? in
 | 
			
		||||
               0)
 | 
			
		||||
                    pr_svrty_criticalln   "offered (NOT ok)"
 | 
			
		||||
                    fileout "sslv2" "NOT ok" "SSLv2 is offered (NOT ok)"
 | 
			
		||||
                    fileout "sslv2" "CRITICAL" "SSLv2 is offered (NOT ok)"
 | 
			
		||||
                    add_tls_offered "ssl2"
 | 
			
		||||
                    ;;
 | 
			
		||||
               1)
 | 
			
		||||
@@ -3225,7 +3368,7 @@ run_protocols() {
 | 
			
		||||
                    ;;
 | 
			
		||||
               5)
 | 
			
		||||
                    pr_svrty_high "CVE-2015-3197: $supported_no_ciph2";
 | 
			
		||||
                    fileout "sslv2" "WARN" "CVE-2015-3197: SSLv2 is $supported_no_ciph2"
 | 
			
		||||
                    fileout "sslv2" "HIGH" "CVE-2015-3197: SSLv2 is $supported_no_ciph2"
 | 
			
		||||
                    add_tls_offered "ssl2"
 | 
			
		||||
                    ;;
 | 
			
		||||
               7)
 | 
			
		||||
@@ -3243,7 +3386,7 @@ run_protocols() {
 | 
			
		||||
     case $? in
 | 
			
		||||
          0)
 | 
			
		||||
               pr_svrty_highln "offered (NOT ok)"
 | 
			
		||||
               fileout "sslv3" "NOT ok" "SSLv3 is offered (NOT ok)"
 | 
			
		||||
               fileout "sslv3" "HIGH" "SSLv3 is offered (NOT ok)"
 | 
			
		||||
               latest_supported="0300"
 | 
			
		||||
               latest_supported_string="SSLv3"
 | 
			
		||||
               add_tls_offered "ssl3"
 | 
			
		||||
@@ -3256,15 +3399,15 @@ run_protocols() {
 | 
			
		||||
               if [[ "$DETECTED_TLS_VERSION" == 03* ]]; then
 | 
			
		||||
                    detected_version_string="TLSv1.$((0x$DETECTED_TLS_VERSION-0x0301))"
 | 
			
		||||
                    pr_svrty_criticalln "server responded with higher version number ($detected_version_string) than requested by client (NOT ok)"
 | 
			
		||||
                    fileout "sslv3" "NOT ok" "SSLv3: server responded with higher version number ($detected_version_string) than requested by client (NOT ok)"
 | 
			
		||||
                    fileout "sslv3" "CRITICAL" "SSLv3: server responded with higher version number ($detected_version_string) than requested by client (NOT ok)"
 | 
			
		||||
               else
 | 
			
		||||
                    pr_svrty_criticalln "server responded with version number ${DETECTED_TLS_VERSION:0:2}.${DETECTED_TLS_VERSION:2:2} (NOT ok)"
 | 
			
		||||
                    fileout "sslv3" "NOT ok" "SSLv3: server responded with version number ${DETECTED_TLS_VERSION:0:2}.${DETECTED_TLS_VERSION:2:2} (NOT ok)"
 | 
			
		||||
                    fileout "sslv3" "CRITICAL" "SSLv3: server responded with version number ${DETECTED_TLS_VERSION:0:2}.${DETECTED_TLS_VERSION:2:2} (NOT ok)"
 | 
			
		||||
               fi
 | 
			
		||||
               ;;
 | 
			
		||||
          5)
 | 
			
		||||
               fileout "sslv3" "WARN" "SSLv3 is $supported_no_ciph1"
 | 
			
		||||
               pr_svrty_high "$supported_no_ciph2"
 | 
			
		||||
               fileout "sslv3" "HIGH" "SSLv3 is $supported_no_ciph1"
 | 
			
		||||
               outln "(may need debugging)"
 | 
			
		||||
               add_tls_offered "ssl3"
 | 
			
		||||
               ;;
 | 
			
		||||
@@ -3294,7 +3437,7 @@ run_protocols() {
 | 
			
		||||
                    fileout "tls1" "INFO" "TLSv1.0 is not offered" # neither good or bad
 | 
			
		||||
               else
 | 
			
		||||
                    pr_svrty_criticalln " -- connection failed rather than downgrading to $latest_supported_string (NOT ok)"
 | 
			
		||||
                    fileout "tls1" "NOT ok" "TLSv1.0: connection failed rather than downgrading to $latest_supported_string (NOT ok)"
 | 
			
		||||
                    fileout "tls1" "CRITICAL" "TLSv1.0: connection failed rather than downgrading to $latest_supported_string (NOT ok)"
 | 
			
		||||
               fi
 | 
			
		||||
               ;;
 | 
			
		||||
          2)
 | 
			
		||||
@@ -3306,10 +3449,10 @@ run_protocols() {
 | 
			
		||||
               elif [[ "$DETECTED_TLS_VERSION" == 03* ]]; then
 | 
			
		||||
                    detected_version_string="TLSv1.$((0x$DETECTED_TLS_VERSION-0x0301))"
 | 
			
		||||
                    pr_svrty_criticalln " -- server responded with higher version number ($detected_version_string) than requested by client"
 | 
			
		||||
                    fileout "tls1" "NOT ok" "TLSv1.0: server responded with higher version number ($detected_version_string) than requested by client (NOT ok)"
 | 
			
		||||
                    fileout "tls1" "CRITICAL" "TLSv1.0: server responded with higher version number ($detected_version_string) than requested by client (NOT ok)"
 | 
			
		||||
               else
 | 
			
		||||
                    pr_svrty_criticalln " -- server responded with version number ${DETECTED_TLS_VERSION:0:2}.${DETECTED_TLS_VERSION:2:2}"
 | 
			
		||||
                    fileout "tls1" "NOT ok" "TLSv1.0: server responded with version number ${DETECTED_TLS_VERSION:0:2}.${DETECTED_TLS_VERSION:2:2} (NOT ok)"
 | 
			
		||||
                    fileout "tls1" "CRITICAL" "TLSv1.0: server responded with version number ${DETECTED_TLS_VERSION:0:2}.${DETECTED_TLS_VERSION:2:2} (NOT ok)"
 | 
			
		||||
               fi
 | 
			
		||||
               ;;
 | 
			
		||||
          5)
 | 
			
		||||
@@ -3343,7 +3486,7 @@ run_protocols() {
 | 
			
		||||
                    fileout "tls1_1" "INFO" "TLSv1.1 is not offered"  # neither good or bad
 | 
			
		||||
               else
 | 
			
		||||
                    pr_svrty_criticalln " -- connection failed rather than downgrading to $latest_supported_string"
 | 
			
		||||
                    fileout "tls1_1" "NOT ok" "TLSv1.1: connection failed rather than downgrading to $latest_supported_string (NOT ok)"
 | 
			
		||||
                    fileout "tls1_1" "CRITICAL" "TLSv1.1: connection failed rather than downgrading to $latest_supported_string (NOT ok)"
 | 
			
		||||
               fi
 | 
			
		||||
               ;;
 | 
			
		||||
          2)
 | 
			
		||||
@@ -3351,17 +3494,17 @@ run_protocols() {
 | 
			
		||||
               if [[ "$DETECTED_TLS_VERSION" == "$latest_supported" ]]; then
 | 
			
		||||
                    [[ $DEBUG -eq 1 ]] && out " -- downgraded"
 | 
			
		||||
                    outln
 | 
			
		||||
                    fileout "tls1_1" "NOT ok" "TLSv1.1 is not offered, and downgraded to a weaker protocol (NOT ok)"
 | 
			
		||||
                    fileout "tls1_1" "CRITICAL" "TLSv1.1 is not offered, and downgraded to a weaker protocol (NOT ok)"
 | 
			
		||||
               elif [[ "$DETECTED_TLS_VERSION" == "0300" ]] && [[ "$latest_supported" == "0301" ]]; then
 | 
			
		||||
                    pr_svrty_criticalln " -- server supports TLSv1.0, but downgraded to SSLv3 (NOT ok)"
 | 
			
		||||
                    fileout "tls1_1" "NOT ok" "TLSv1.1 is not offered, and downgraded to SSLv3 rather than TLSv1.0 (NOT ok)"
 | 
			
		||||
                    fileout "tls1_1" "CRITICAL" "TLSv1.1 is not offered, and downgraded to SSLv3 rather than TLSv1.0 (NOT ok)"
 | 
			
		||||
               elif [[ "$DETECTED_TLS_VERSION" == 03* ]] && [[ 0x$DETECTED_TLS_VERSION -gt 0x0302 ]]; then
 | 
			
		||||
                    detected_version_string="TLSv1.$((0x$DETECTED_TLS_VERSION-0x0301))"
 | 
			
		||||
                    pr_svrty_criticalln " -- server responded with higher version number ($detected_version_string) than requested by client (NOT ok)"
 | 
			
		||||
                    fileout "tls1_1" "NOT ok" "TLSv1.1 is not offered, server responded with higher version number ($detected_version_string) than requested by client (NOT ok)"
 | 
			
		||||
                    fileout "tls1_1" "CRITICAL" "TLSv1.1 is not offered, server responded with higher version number ($detected_version_string) than requested by client (NOT ok)"
 | 
			
		||||
               else
 | 
			
		||||
                    pr_svrty_criticalln " -- server responded with version number ${DETECTED_TLS_VERSION:0:2}.${DETECTED_TLS_VERSION:2:2} (NOT ok)"
 | 
			
		||||
                    fileout "tls1" "NOT ok" "TLSv1.1: server responded with version number ${DETECTED_TLS_VERSION:0:2}.${DETECTED_TLS_VERSION:2:2} (NOT ok)"
 | 
			
		||||
                    fileout "tls1" "CRITICAL" "TLSv1.1: server responded with version number ${DETECTED_TLS_VERSION:0:2}.${DETECTED_TLS_VERSION:2:2} (NOT ok)"
 | 
			
		||||
               fi
 | 
			
		||||
               ;;
 | 
			
		||||
          5)
 | 
			
		||||
@@ -3394,7 +3537,7 @@ run_protocols() {
 | 
			
		||||
                    fileout "tls1_2" "MEDIUM" "TLSv1.2 is not offered" # no GCM, penalty
 | 
			
		||||
               else
 | 
			
		||||
                    pr_svrty_criticalln " -- connection failed rather than downgrading to $latest_supported_string"
 | 
			
		||||
                    fileout "tls1_1" "NOT ok" "TLSv1.2: connection failed rather than downgrading to $latest_supported_string"
 | 
			
		||||
                    fileout "tls1_1" "CRITICAL" "TLSv1.2: connection failed rather than downgrading to $latest_supported_string"
 | 
			
		||||
               fi
 | 
			
		||||
               ;;
 | 
			
		||||
          2)
 | 
			
		||||
@@ -3410,13 +3553,13 @@ run_protocols() {
 | 
			
		||||
                    fileout "tls1_2" "MEDIUM" "TLSv1.2 is not offered and downgraded to a weaker protocol"
 | 
			
		||||
               elif [[ "$DETECTED_TLS_VERSION" == 03* ]] && [[ 0x$DETECTED_TLS_VERSION -lt 0x$latest_supported ]]; then
 | 
			
		||||
                    pr_svrty_criticalln " -- server supports $latest_supported_string, but downgraded to $detected_version_string"
 | 
			
		||||
                    fileout "tls1_2" "NOT ok" "TLSv1.2 is not offered, and downgraded to $detected_version_string rather than $latest_supported_string (NOT ok)"
 | 
			
		||||
                    fileout "tls1_2" "CRITICAL" "TLSv1.2 is not offered, and downgraded to $detected_version_string rather than $latest_supported_string (NOT ok)"
 | 
			
		||||
               elif [[ "$DETECTED_TLS_VERSION" == 03* ]] && [[ 0x$DETECTED_TLS_VERSION -gt 0x0303 ]]; then
 | 
			
		||||
                    pr_svrty_criticalln " -- server responded with higher version number ($detected_version_string) than requested by client"
 | 
			
		||||
                    fileout "tls1_2" "NOT ok" "TLSv1.2 is not offered, server responded with higher version number ($detected_version_string) than requested by client (NOT ok)"
 | 
			
		||||
                    fileout "tls1_2" "CRITICAL" "TLSv1.2 is not offered, server responded with higher version number ($detected_version_string) than requested by client (NOT ok)"
 | 
			
		||||
               else
 | 
			
		||||
                    pr_svrty_criticalln " -- server responded with version number ${DETECTED_TLS_VERSION:0:2}.${DETECTED_TLS_VERSION:2:2}"
 | 
			
		||||
                    fileout "tls1" "NOT ok" "TLSv1.2: server responded with version number ${DETECTED_TLS_VERSION:0:2}.${DETECTED_TLS_VERSION:2:2} (NOT ok)"
 | 
			
		||||
                    fileout "tls1" "CRITICAL" "TLSv1.2: server responded with version number ${DETECTED_TLS_VERSION:0:2}.${DETECTED_TLS_VERSION:2:2} (NOT ok)"
 | 
			
		||||
               fi
 | 
			
		||||
               ;;
 | 
			
		||||
          5)
 | 
			
		||||
@@ -3586,7 +3729,7 @@ run_server_preference() {
 | 
			
		||||
          if [[ "$cipher1" != "$cipher2" ]]; then
 | 
			
		||||
               pr_svrty_high "nope (NOT ok)"
 | 
			
		||||
               remark4default_cipher=" (limited sense as client will pick)"
 | 
			
		||||
               fileout "order" "NOT ok" "Server does NOT set a cipher order (NOT ok)"
 | 
			
		||||
               fileout "order" "HIGH" "Server does NOT set a cipher order (NOT ok)"
 | 
			
		||||
          else
 | 
			
		||||
               pr_done_best "yes (OK)"
 | 
			
		||||
               remark4default_cipher=""
 | 
			
		||||
@@ -3618,11 +3761,11 @@ run_server_preference() {
 | 
			
		||||
                    ;;
 | 
			
		||||
               *SSLv2)
 | 
			
		||||
                    pr_svrty_criticalln $default_proto
 | 
			
		||||
                    fileout "order_proto" "NOT ok" "Default protocol SSLv2"
 | 
			
		||||
                    fileout "order_proto" "CRITICAL" "Default protocol SSLv2"
 | 
			
		||||
                    ;;
 | 
			
		||||
               *SSLv3)
 | 
			
		||||
                    pr_svrty_criticalln $default_proto
 | 
			
		||||
                    fileout "order_proto" "NOT ok" "Default protocol SSLv3"
 | 
			
		||||
                    fileout "order_proto" "CRITICAL" "Default protocol SSLv3"
 | 
			
		||||
                    ;;
 | 
			
		||||
               "")
 | 
			
		||||
                    pr_warning "default proto empty"
 | 
			
		||||
@@ -3644,11 +3787,11 @@ run_server_preference() {
 | 
			
		||||
          case "$default_cipher" in
 | 
			
		||||
               *NULL*|*EXP*)
 | 
			
		||||
                    pr_svrty_critical "$default_cipher"
 | 
			
		||||
                    fileout "order_cipher" "NOT ok" "Default cipher: $default_cipher$(read_dhbits_from_file "$TMPFILE") (NOT ok)  $remark4default_cipher"
 | 
			
		||||
                    fileout "order_cipher" "CRITICAL" "Default cipher: $default_cipher$(read_dhbits_from_file "$TMPFILE") (NOT ok)  $remark4default_cipher"
 | 
			
		||||
                    ;;
 | 
			
		||||
               *RC4*)
 | 
			
		||||
                    pr_svrty_high "$default_cipher"
 | 
			
		||||
                    fileout "order_cipher" "NOT ok" "Default cipher: $default_cipher$(read_dhbits_from_file "$TMPFILE") (NOT ok)  remark4default_cipher"
 | 
			
		||||
                    fileout "order_cipher" "HIGH" "Default cipher: $default_cipher$(read_dhbits_from_file "$TMPFILE") (NOT ok)  remark4default_cipher"
 | 
			
		||||
                    ;;
 | 
			
		||||
               *CBC*)
 | 
			
		||||
                    pr_svrty_medium "$default_cipher"
 | 
			
		||||
@@ -3660,7 +3803,7 @@ run_server_preference() {
 | 
			
		||||
                    ;;   # best ones
 | 
			
		||||
               ECDHE*AES*)
 | 
			
		||||
                    pr_svrty_minor "$default_cipher"
 | 
			
		||||
                    fileout "order_cipher" "WARN" "Default cipher: $default_cipher$(read_dhbits_from_file "$TMPFILE") (cbc)  $remark4default_cipher"
 | 
			
		||||
                    fileout "order_cipher" "LOW" "Default cipher: $default_cipher$(read_dhbits_from_file "$TMPFILE") (cbc)  $remark4default_cipher"
 | 
			
		||||
                    ;;  # it's CBC. --> lucky13
 | 
			
		||||
               "")
 | 
			
		||||
                    pr_warning "default cipher empty" ;
 | 
			
		||||
@@ -4032,7 +4175,7 @@ determine_trust() {
 | 
			
		||||
		     # all failed (we assume with the same issue), we're displaying the reason
 | 
			
		||||
               out " "
 | 
			
		||||
			verify_retcode_helper "${verify_retcode[1]}"
 | 
			
		||||
               fileout "${json_prefix}chain_of_trust" "NOT ok" "All certificate trust checks failed: $(verify_retcode_helper "${verify_retcode[1]}"). $addtl_warning"
 | 
			
		||||
               fileout "${json_prefix}chain_of_trust" "CRITICAL" "All certificate trust checks failed: $(verify_retcode_helper "${verify_retcode[1]}"). $addtl_warning"
 | 
			
		||||
		else
 | 
			
		||||
			# is one ok and the others not ==> display the culprit store
 | 
			
		||||
			if $some_ok ; then
 | 
			
		||||
@@ -4055,7 +4198,7 @@ determine_trust() {
 | 
			
		||||
                    [[ "$DEBUG" -eq 0 ]] && out "$spaces"
 | 
			
		||||
				pr_done_good "OK: $ok_was"
 | 
			
		||||
               fi
 | 
			
		||||
               fileout "${json_prefix}chain_of_trust" "NOT ok" "Some certificate trust checks failed : OK : $ok_was  NOT ok: $notok_was $addtl_warning"
 | 
			
		||||
               fileout "${json_prefix}chain_of_trust" "CRITICAL" "Some certificate trust checks failed : OK : $ok_was  NOT ok: $notok_was $addtl_warning"
 | 
			
		||||
          fi
 | 
			
		||||
          [[ -n "$addtl_warning" ]] && out "\n$spaces" && pr_warning "$addtl_warning"
 | 
			
		||||
	fi
 | 
			
		||||
@@ -4490,15 +4633,15 @@ certificate_info() {
 | 
			
		||||
                    ;;
 | 
			
		||||
          md2*)
 | 
			
		||||
               pr_svrty_criticalln "MD2"
 | 
			
		||||
               fileout "${json_prefix}algorithm" "NOT ok" "Signature Algorithm: MD2 (NOT ok)"
 | 
			
		||||
               fileout "${json_prefix}algorithm" "CRITICAL" "Signature Algorithm: MD2 (NOT ok)"
 | 
			
		||||
               ;;
 | 
			
		||||
          md4*)
 | 
			
		||||
               pr_svrty_criticalln "MD4"
 | 
			
		||||
               fileout "${json_prefix}algorithm" "NOT ok" "Signature Algorithm: MD4 (NOT ok)"
 | 
			
		||||
               fileout "${json_prefix}algorithm" "CRITICAL" "Signature Algorithm: MD4 (NOT ok)"
 | 
			
		||||
               ;;
 | 
			
		||||
          md5*)
 | 
			
		||||
               pr_svrty_criticalln "MD5"
 | 
			
		||||
               fileout "${json_prefix}algorithm" "NOT ok" "Signature Algorithm: MD5 (NOT ok)"
 | 
			
		||||
               fileout "${json_prefix}algorithm" "CRITICAL" "Signature Algorithm: MD5 (NOT ok)"
 | 
			
		||||
               ;;
 | 
			
		||||
          *)
 | 
			
		||||
               out "$cert_sig_algo ("
 | 
			
		||||
@@ -4529,10 +4672,10 @@ certificate_info() {
 | 
			
		||||
          if [[ $cert_key_algo =~ ecdsa ]] || [[ $cert_key_algo =~ ecPublicKey  ]]; then
 | 
			
		||||
               if [[ "$cert_keysize" -le 110 ]]; then       # a guess
 | 
			
		||||
                    pr_svrty_critical "$cert_keysize"
 | 
			
		||||
                    fileout "${json_prefix}key_size" "NOT ok" "Server keys $cert_keysize EC bits (NOT ok)"
 | 
			
		||||
                    fileout "${json_prefix}key_size" "CRITICAL" "Server keys $cert_keysize EC bits (NOT ok)"
 | 
			
		||||
               elif [[ "$cert_keysize" -le 123 ]]; then    # a guess
 | 
			
		||||
                    pr_svrty_high "$cert_keysize"
 | 
			
		||||
                    fileout "${json_prefix}key_size" "NOT ok" "Server keys $cert_keysize EC bits (NOT ok)"
 | 
			
		||||
                    fileout "${json_prefix}key_size" "HIGH" "Server keys $cert_keysize EC bits (NOT ok)"
 | 
			
		||||
               elif [[ "$cert_keysize" -le 163 ]]; then
 | 
			
		||||
                    pr_svrty_medium "$cert_keysize"
 | 
			
		||||
                    fileout "${json_prefix}key_size" "MEDIUM" "Server keys $cert_keysize EC bits"
 | 
			
		||||
@@ -4552,11 +4695,11 @@ certificate_info() {
 | 
			
		||||
               if [[ "$cert_keysize" -le 512 ]]; then
 | 
			
		||||
                    pr_svrty_critical "$cert_keysize"
 | 
			
		||||
                    outln " bits"
 | 
			
		||||
                    fileout "${json_prefix}key_size" "NOT ok" "Server keys $cert_keysize bits (NOT ok)"
 | 
			
		||||
                    fileout "${json_prefix}key_size" "CRITICAL" "Server keys $cert_keysize bits (NOT ok)"
 | 
			
		||||
               elif [[ "$cert_keysize" -le 768 ]]; then
 | 
			
		||||
                    pr_svrty_high "$cert_keysize"
 | 
			
		||||
                    outln " bits"
 | 
			
		||||
                    fileout "${json_prefix}key_size" "NOT ok" "Server keys $cert_keysize bits (NOT ok)"
 | 
			
		||||
                    fileout "${json_prefix}key_size" "HIGH" "Server keys $cert_keysize bits (NOT ok)"
 | 
			
		||||
               elif [[ "$cert_keysize" -le 1024 ]]; then
 | 
			
		||||
                    pr_svrty_medium "$cert_keysize"
 | 
			
		||||
                    outln " bits"
 | 
			
		||||
@@ -4666,7 +4809,7 @@ certificate_info() {
 | 
			
		||||
 | 
			
		||||
     if [[ "$issuer_O" == "issuer=" ]] || [[ "$issuer_O" == "issuer= " ]] || [[ "$issuer_CN" == "$cn" ]]; then
 | 
			
		||||
          pr_svrty_criticalln "self-signed (NOT ok)"
 | 
			
		||||
          fileout "${json_prefix}issuer" "NOT ok" "Issuer: selfsigned (NOT ok)"
 | 
			
		||||
          fileout "${json_prefix}issuer" "CRITICAL" "Issuer: selfsigned (NOT ok)"
 | 
			
		||||
     else
 | 
			
		||||
          issuerfinding="$(pr_dquoted "$issuer_CN")"
 | 
			
		||||
          if [[ -z "$issuer_O" ]] && [[ -n "$issuer_DC" ]]; then
 | 
			
		||||
@@ -4820,7 +4963,7 @@ certificate_info() {
 | 
			
		||||
     if ! echo $expire | grep -qw not; then
 | 
			
		||||
          pr_svrty_critical "expired!"
 | 
			
		||||
          expfinding="expired!"
 | 
			
		||||
          expok="NOT ok"
 | 
			
		||||
          expok="CRITICAL"
 | 
			
		||||
     else
 | 
			
		||||
          secs2warn=$((24 * 60 * 60 * days2warn2))  # low threshold first
 | 
			
		||||
          expire=$($OPENSSL x509 -in $HOSTCERT -checkend $secs2warn 2>>$ERRFILE)
 | 
			
		||||
@@ -4833,12 +4976,12 @@ certificate_info() {
 | 
			
		||||
               else
 | 
			
		||||
                    pr_svrty_medium "expires < $days2warn1 days ($days2expire)"
 | 
			
		||||
                    expfinding+="expires < $days2warn1 days ($days2expire)"
 | 
			
		||||
                    expok="WARN"
 | 
			
		||||
                    expok="MEDIUM"
 | 
			
		||||
               fi
 | 
			
		||||
          else
 | 
			
		||||
               pr_svrty_high "expires < $days2warn2 days ($days2expire) !"
 | 
			
		||||
               expfinding+="expires < $days2warn2 days ($days2expire) !"
 | 
			
		||||
               expok="NOT ok"
 | 
			
		||||
               expok="HIGH"
 | 
			
		||||
          fi
 | 
			
		||||
     fi
 | 
			
		||||
     outln " ($startdate --> $enddate)"
 | 
			
		||||
@@ -4852,7 +4995,7 @@ certificate_info() {
 | 
			
		||||
     crl="$($OPENSSL x509 -in $HOSTCERT -noout -text 2>>$ERRFILE | grep -A 4 "CRL Distribution" | grep URI | sed 's/^.*URI://')"
 | 
			
		||||
     if [[ -z "$crl" ]]; then
 | 
			
		||||
          pr_svrty_highln "--"
 | 
			
		||||
          fileout "${json_prefix}crl" "NOT ok" "No CRL provided (NOT ok)"
 | 
			
		||||
          fileout "${json_prefix}crl" "HIGH" "No CRL provided (NOT ok)"
 | 
			
		||||
     elif grep -q http <<< "$crl"; then
 | 
			
		||||
          if [[ $(count_lines "$crl") -eq 1 ]]; then
 | 
			
		||||
               outln "$crl"
 | 
			
		||||
@@ -4870,7 +5013,7 @@ certificate_info() {
 | 
			
		||||
     ocsp_uri=$($OPENSSL x509 -in $HOSTCERT -noout -ocsp_uri 2>>$ERRFILE)
 | 
			
		||||
     if [[ -z "$ocsp_uri" ]]; then
 | 
			
		||||
          pr_svrty_highln "--"
 | 
			
		||||
          fileout "${json_prefix}ocsp_uri" "NOT ok" "OCSP URI : -- (NOT ok)"
 | 
			
		||||
          fileout "${json_prefix}ocsp_uri" "HIGH" "OCSP URI : -- (NOT ok)"
 | 
			
		||||
     else
 | 
			
		||||
          outln "$ocsp_uri"
 | 
			
		||||
          fileout "${json_prefix}ocsp_uri" "INFO" "OCSP URI : $ocsp_uri"
 | 
			
		||||
@@ -4879,7 +5022,7 @@ certificate_info() {
 | 
			
		||||
     out "$indent"; pr_bold " OCSP stapling                "
 | 
			
		||||
     if grep -a "OCSP response" <<<"$ocsp_response" | grep -q "no response sent" ; then
 | 
			
		||||
          pr_svrty_minor "--"
 | 
			
		||||
          fileout "${json_prefix}ocsp_stapling" "INFO" "OCSP stapling : not offered"
 | 
			
		||||
          fileout "${json_prefix}ocsp_stapling" "LOW" "OCSP stapling : not offered"
 | 
			
		||||
     else
 | 
			
		||||
          if grep -a "OCSP Response Status" <<<"$ocsp_response_status" | grep -q successful; then
 | 
			
		||||
               pr_done_good "offered"
 | 
			
		||||
@@ -5077,7 +5220,7 @@ run_server_defaults() {
 | 
			
		||||
          unit=$(echo $sessticket_str | grep -a lifetime | sed -e 's/^.*'"$lifetime"'//' -e 's/[ ()]//g')
 | 
			
		||||
          out "$lifetime $unit "
 | 
			
		||||
          pr_svrty_minorln "(PFS requires session ticket keys to be rotated <= daily)"
 | 
			
		||||
          fileout "session_ticket" "INFO" "TLS session tickes RFC 5077 valid for $lifetime $unit (PFS requires session ticket keys to be rotated at least daily)"
 | 
			
		||||
          fileout "session_ticket" "LOW" "TLS session tickes RFC 5077 valid for $lifetime $unit (PFS requires session ticket keys to be rotated at least daily)"
 | 
			
		||||
     fi
 | 
			
		||||
 | 
			
		||||
     pr_bold " SSL Session ID support       "
 | 
			
		||||
@@ -5189,7 +5332,7 @@ run_pfs() {
 | 
			
		||||
 | 
			
		||||
          if ! "$pfs_offered"; then
 | 
			
		||||
               pr_svrty_medium "WARN: no PFS ciphers found"
 | 
			
		||||
               fileout "pfs_ciphers" "NOT ok" "(Perfect) Forward Secrecy Ciphers: no PFS ciphers found (NOT ok)"
 | 
			
		||||
               fileout "pfs_ciphers" "MEDIUM" "(Perfect) Forward Secrecy Ciphers: no PFS ciphers found (NOT ok)"
 | 
			
		||||
          else
 | 
			
		||||
               fileout "pfs_ciphers" "INFO" "(Perfect) Forward Secrecy Ciphers: $pfs_ciphers"
 | 
			
		||||
          fi
 | 
			
		||||
@@ -6797,7 +6940,7 @@ run_heartbleed(){
 | 
			
		||||
               else
 | 
			
		||||
                    rm "$SOCK_REPLY_FILE"
 | 
			
		||||
                    pr_svrty_critical "VULNERABLE (NOT ok)"
 | 
			
		||||
                    fileout "heartbleed" "NOT ok" "Heartbleed (CVE-2014-0160): VULNERABLE (NOT ok)$append"
 | 
			
		||||
                    fileout "heartbleed" "CRITICAL" "Heartbleed (CVE-2014-0160): VULNERABLE (NOT ok)$append"
 | 
			
		||||
                    ret=1
 | 
			
		||||
                    break
 | 
			
		||||
               fi
 | 
			
		||||
@@ -6823,7 +6966,7 @@ run_heartbleed(){
 | 
			
		||||
               out "likely "
 | 
			
		||||
               pr_svrty_critical "VULNERABLE (NOT ok)"
 | 
			
		||||
               [[ $DEBUG -ge 1 ]] && out " use debug >=2 to confirm"
 | 
			
		||||
               fileout "heartbleed" "NOT ok" "Heartbleed (CVE-2014-0160): likely VULNERABLE (NOT ok)$append"
 | 
			
		||||
               fileout "heartbleed" "CRITICAL" "Heartbleed (CVE-2014-0160): likely VULNERABLE (NOT ok)$append"
 | 
			
		||||
          fi
 | 
			
		||||
     else
 | 
			
		||||
          # for the repeated tries we did that already
 | 
			
		||||
@@ -6958,9 +7101,9 @@ run_ccs_injection(){
 | 
			
		||||
     else
 | 
			
		||||
          pr_svrty_critical "VULNERABLE (NOT ok)"
 | 
			
		||||
          if [[ $retval -eq 3 ]]; then
 | 
			
		||||
               fileout "ccs" "NOT ok" "CCS (CVE-2014-0224): VULNERABLE (NOT ok) (timed out)"
 | 
			
		||||
               fileout "ccs" "CRITICAL" "CCS (CVE-2014-0224): VULNERABLE (NOT ok) (timed out)"
 | 
			
		||||
          else
 | 
			
		||||
               fileout "ccs" "NOT ok" "CCS (CVE-2014-0224): VULNERABLE (NOT ok)"
 | 
			
		||||
               fileout "ccs" "CRITICAL" "CCS (CVE-2014-0224): VULNERABLE (NOT ok)"
 | 
			
		||||
          fi
 | 
			
		||||
          ret=1
 | 
			
		||||
     fi
 | 
			
		||||
@@ -6991,7 +7134,7 @@ run_renego() {
 | 
			
		||||
          case $sec_renego in
 | 
			
		||||
               0)
 | 
			
		||||
                    pr_svrty_criticalln "VULNERABLE (NOT ok)"
 | 
			
		||||
                    fileout "secure_renego" "NOT ok" "Secure Renegotiation (CVE-2009-3555) : VULNERABLE (NOT ok)"
 | 
			
		||||
                    fileout "secure_renego" "CRITICAL" "Secure Renegotiation (CVE-2009-3555) : VULNERABLE (NOT ok)"
 | 
			
		||||
                    ;;
 | 
			
		||||
               1)
 | 
			
		||||
                    pr_done_bestln "not vulnerable (OK)"
 | 
			
		||||
@@ -7108,7 +7251,7 @@ run_crime() {
 | 
			
		||||
     else
 | 
			
		||||
          if [[ $SERVICE == "HTTP" ]]; then
 | 
			
		||||
               pr_svrty_high "VULNERABLE (NOT ok)"
 | 
			
		||||
               fileout "crime" "NOT ok" "CRIME, TLS (CVE-2012-4929) : VULNERABLE (NOT ok)"
 | 
			
		||||
               fileout "crime" "HIGH" "CRIME, TLS (CVE-2012-4929) : VULNERABLE (NOT ok)"
 | 
			
		||||
          else
 | 
			
		||||
               pr_svrty_medium "VULNERABLE but not using HTTP: probably no exploit known"
 | 
			
		||||
               fileout "crime" "MEDIUM" "CRIME, TLS (CVE-2012-4929) : VULNERABLE (WARN), but not using HTTP: probably no exploit known"
 | 
			
		||||
@@ -7209,7 +7352,7 @@ run_breach() {
 | 
			
		||||
          pr_svrty_high "potentially NOT ok, uses $result HTTP compression."
 | 
			
		||||
          outln "$disclaimer"
 | 
			
		||||
          outln "$spaces$when_makesense"
 | 
			
		||||
          fileout "breach" "NOT ok" "BREACH (CVE-2013-3587) : potentially VULNERABLE, uses $result HTTP compression. $disclaimer ($when_makesense)"
 | 
			
		||||
          fileout "breach" "HIGH" "BREACH (CVE-2013-3587) : potentially VULNERABLE, uses $result HTTP compression. $disclaimer ($when_makesense)"
 | 
			
		||||
          ret=1
 | 
			
		||||
     fi
 | 
			
		||||
     # Any URL can be vulnerable. I am testing now only the given URL!
 | 
			
		||||
@@ -7235,7 +7378,7 @@ run_ssl_poodle() {
 | 
			
		||||
     [[ "$DEBUG" -eq 2 ]] && egrep -q "error|failure" $ERRFILE | egrep -av "unable to get local|verify error"
 | 
			
		||||
     if [[ $sclient_success -eq 0 ]]; then
 | 
			
		||||
          pr_svrty_high "VULNERABLE (NOT ok)"; out ", uses SSLv3+CBC (check TLS_FALLBACK_SCSV mitigation below)"
 | 
			
		||||
          fileout "poodle_ssl" "NOT ok" "POODLE, SSL (CVE-2014-3566) : VULNERABLE (NOT ok), uses SSLv3+CBC (check if TLS_FALLBACK_SCSV mitigation is used)"
 | 
			
		||||
          fileout "poodle_ssl" "HIGH" "POODLE, SSL (CVE-2014-3566) : VULNERABLE (NOT ok), uses SSLv3+CBC (check if TLS_FALLBACK_SCSV mitigation is used)"
 | 
			
		||||
     else
 | 
			
		||||
          pr_done_best "not vulnerable (OK)"
 | 
			
		||||
          fileout "poodle_ssl" "OK" "POODLE, SSL (CVE-2014-3566) : not vulnerable (OK)"
 | 
			
		||||
@@ -7356,7 +7499,7 @@ run_freak() {
 | 
			
		||||
     [[ $DEBUG -eq 2 ]] && egrep -a "error|failure" $ERRFILE | egrep -av "unable to get local|verify error"
 | 
			
		||||
     if [[ $sclient_success -eq 0 ]]; then
 | 
			
		||||
          pr_svrty_critical "VULNERABLE (NOT ok)"; out ", uses EXPORT RSA ciphers"
 | 
			
		||||
          fileout "freak" "NOT ok" "FREAK (CVE-2015-0204) : VULNERABLE (NOT ok), uses EXPORT RSA ciphers"
 | 
			
		||||
          fileout "freak" "CRITICAL" "FREAK (CVE-2015-0204) : VULNERABLE (NOT ok), uses EXPORT RSA ciphers"
 | 
			
		||||
     else
 | 
			
		||||
          pr_done_best "not vulnerable (OK)"; out "$addtl_warning"
 | 
			
		||||
          fileout "freak" "OK" "FREAK (CVE-2015-0204) : not vulnerable (OK) $addtl_warning"
 | 
			
		||||
@@ -7408,7 +7551,7 @@ run_logjam() {
 | 
			
		||||
 | 
			
		||||
     if [[ $sclient_success -eq 0 ]]; then
 | 
			
		||||
          pr_svrty_critical "VULNERABLE (NOT ok)"; out ", uses DHE EXPORT ciphers, common primes not checked."
 | 
			
		||||
          fileout "logjam" "NOT ok" "LOGJAM (CVE-2015-4000) : VULNERABLE (NOT ok), uses DHE EXPORT ciphers, common primes not checked."
 | 
			
		||||
          fileout "logjam" "CRITICAL" "LOGJAM (CVE-2015-4000) : VULNERABLE (NOT ok), uses DHE EXPORT ciphers, common primes not checked."
 | 
			
		||||
     else
 | 
			
		||||
          pr_done_best "not vulnerable (OK)"; out "$addtl_warning"
 | 
			
		||||
          fileout "logjam" "OK" "LOGJAM (CVE-2015-4000) : not vulnerable (OK) $addtl_warning"
 | 
			
		||||
@@ -7445,7 +7588,7 @@ run_drown() {
 | 
			
		||||
               outln " (rerun with DEBUG >=2)"
 | 
			
		||||
               [[ $DEBUG -ge 3 ]] && hexdump -C "$TEMPDIR/$NODEIP.sslv2_sockets.dd" | head -1
 | 
			
		||||
               ret=7
 | 
			
		||||
               fileout "drown" "MINOR_ERROR" "SSLv2: received a strange SSLv2 reply (rerun with DEBUG>=2)"
 | 
			
		||||
               fileout "drown" "WARN" "SSLv2: received a strange SSLv2 reply (rerun with DEBUG>=2)"
 | 
			
		||||
               ;;
 | 
			
		||||
          3)   # vulnerable
 | 
			
		||||
               lines=$(count_lines "$(hexdump -C "$TEMPDIR/$NODEIP.sslv2_sockets.dd" 2>/dev/null)")
 | 
			
		||||
@@ -7454,10 +7597,10 @@ 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" "HIGH" "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" "CRITICAL" "VULNERABLE (NOT ok), SSLv2 offered with $nr_ciphers_detected ciphers"
 | 
			
		||||
                    fi
 | 
			
		||||
               fi
 | 
			
		||||
               ret=1
 | 
			
		||||
@@ -7635,7 +7778,7 @@ run_beast(){
 | 
			
		||||
                    pr_svrty_minor "VULNERABLE"
 | 
			
		||||
                    outln " -- but also supports higher protocols (possible mitigation):$higher_proto_supported"
 | 
			
		||||
               fi
 | 
			
		||||
               fileout "beast" "MINOR" "BEAST (CVE-2011-3389) : VULNERABLE -- but also supports higher protocols (possible mitigation):$higher_proto_supported"
 | 
			
		||||
               fileout "beast" "LOW" "BEAST (CVE-2011-3389) : VULNERABLE -- but also supports higher protocols (possible mitigation):$higher_proto_supported"
 | 
			
		||||
          else
 | 
			
		||||
               if "$WIDE"; then
 | 
			
		||||
                    outln
 | 
			
		||||
@@ -7731,7 +7874,7 @@ run_rc4() {
 | 
			
		||||
          done < <($OPENSSL ciphers -V $rc4_ciphers_list:@STRENGTH)
 | 
			
		||||
          outln
 | 
			
		||||
          "$WIDE" && pr_svrty_high "VULNERABLE (NOT ok)"
 | 
			
		||||
          fileout "rc4" "NOT ok" "RC4 (CVE-2013-2566, CVE-2015-2808) : VULNERABLE (NOT ok) Detected ciphers: $rc4_detected"
 | 
			
		||||
          fileout "rc4" "HIGH" "RC4 (CVE-2013-2566, CVE-2015-2808) : VULNERABLE (NOT ok) Detected ciphers: $rc4_detected"
 | 
			
		||||
     else
 | 
			
		||||
          pr_done_goodln "no RC4 ciphers detected (OK)"
 | 
			
		||||
          fileout "rc4" "OK" "RC4 (CVE-2013-2566, CVE-2015-2808) : not vulnerable (OK)"
 | 
			
		||||
@@ -7762,7 +7905,7 @@ run_tls_truncation() {
 | 
			
		||||
 | 
			
		||||
old_fart() {
 | 
			
		||||
     outln "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 ."
 | 
			
		||||
     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 ."
 | 
			
		||||
     fatal "Your $OPENSSL $OSSL_VER version is an old fart... . It doesn\'t make much sense to proceed." -5
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -8042,9 +8185,12 @@ file output options (can also be preset via environment variables):
 | 
			
		||||
     --logfile <logfile>           logs stdout to <file/NODE-YYYYMMDD-HHMM.log> if file is a dir or to specified log file
 | 
			
		||||
     --json                        additional output of findings to JSON file <NODE-YYYYMMDD-HHMM.json> in cwd
 | 
			
		||||
     --jsonfile <jsonfile>         additional output to JSON and output JSON to the specified file
 | 
			
		||||
     --json-pretty                 additional pretty structed output of findings to JSON file <NODE-YYYYMMDD-HHMM.json> in cwd
 | 
			
		||||
     --jsonfile-pretty <jsonfile>  additional pretty structed output to JSON and output JSON to the specified file
 | 
			
		||||
     --csv                         additional output of findings to CSV file  <NODE-YYYYMMDD-HHMM.csv> in cwd
 | 
			
		||||
     --csvfile <csvfile>           set output to CSV and output CSV to the specified file
 | 
			
		||||
     --append                      if <csvfile> or <jsonfile> exists rather append then overwrite
 | 
			
		||||
     --severity <severity>         severities with lower level will be filtered
 | 
			
		||||
 | 
			
		||||
All options requiring a value can also be called with '=' e.g. testssl.sh -t=smtp --wide --openssl=/usr/bin/openssl <URI>.
 | 
			
		||||
 | 
			
		||||
@@ -8712,7 +8858,7 @@ prepare_logging() {
 | 
			
		||||
          #exec 2> >(tee -a ${LOGFILE} >&2)
 | 
			
		||||
     fi
 | 
			
		||||
 | 
			
		||||
     if "$do_json"; then
 | 
			
		||||
     if "$do_json" || "$do_pretty_json"; then
 | 
			
		||||
          if [[ -z "$JSONFILE" ]]; then
 | 
			
		||||
               JSONFILE=$fname_prefix-$(date +"%Y%m%d-%H%M".json)
 | 
			
		||||
          elif [[ -d "$JSONFILE" ]]; then
 | 
			
		||||
@@ -9303,6 +9449,7 @@ initialize_globals() {
 | 
			
		||||
     do_mass_testing=false
 | 
			
		||||
     do_logging=false
 | 
			
		||||
     do_json=false
 | 
			
		||||
     do_pretty_json=false
 | 
			
		||||
     do_csv=false
 | 
			
		||||
     do_pfs=false
 | 
			
		||||
     do_protocols=false
 | 
			
		||||
@@ -9646,6 +9793,18 @@ parse_cmd_line() {
 | 
			
		||||
                    [[ $? -eq 0 ]] && shift
 | 
			
		||||
                    do_json=true
 | 
			
		||||
                    ;;
 | 
			
		||||
               --json-pretty)
 | 
			
		||||
                    do_pretty_json=true
 | 
			
		||||
                    ;;
 | 
			
		||||
               --jsonfile-pretty|--jsonfile-pretty=*)
 | 
			
		||||
                    JSONFILE=$(parse_opt_equal_sign "$1" "$2")
 | 
			
		||||
                    [[ $? -eq 0 ]] && shift
 | 
			
		||||
                    do_pretty_json=true
 | 
			
		||||
                    ;;
 | 
			
		||||
               --severity|--severity=*)
 | 
			
		||||
                    set_severity_level "$(parse_opt_equal_sign "$1" "$2")"
 | 
			
		||||
                    [[ $? -eq 0 ]] && shift
 | 
			
		||||
                    ;;
 | 
			
		||||
               --csv)
 | 
			
		||||
                    do_csv=true
 | 
			
		||||
                    ;;   # DEFINITION of CSVFILE is not arg specified: automagically in parse_hn_port()
 | 
			
		||||
@@ -9740,11 +9899,16 @@ reset_hostdepended_vars() {
 | 
			
		||||
 | 
			
		||||
lets_roll() {
 | 
			
		||||
     local ret
 | 
			
		||||
     local section_number=1
 | 
			
		||||
 | 
			
		||||
     [[ -z "$NODEIP" ]] && fatal "$NODE doesn't resolve to an IP address" 2
 | 
			
		||||
     nodeip_to_proper_ip6
 | 
			
		||||
     reset_hostdepended_vars
 | 
			
		||||
     determine_rdns
 | 
			
		||||
 | 
			
		||||
     START_TIME=$(date +%s)
 | 
			
		||||
 | 
			
		||||
     fileout_section_header $section_number false && ((section_number++))
 | 
			
		||||
     determine_service "$1"        # any starttls service goes here
 | 
			
		||||
 | 
			
		||||
     $do_tls_sockets && [[ $TLS_LOW_BYTE -eq 22 ]] && { sslv2_sockets "" "true"; echo "$?" ; exit 0; }
 | 
			
		||||
@@ -9752,16 +9916,26 @@ lets_roll() {
 | 
			
		||||
     $do_test_just_one && test_just_one ${single_cipher}
 | 
			
		||||
 | 
			
		||||
     # all top level functions  now following have the prefix "run_"
 | 
			
		||||
     fileout_section_header $section_number true && ((section_number++))
 | 
			
		||||
     $do_protocols && { run_protocols; ret=$(($? + ret)); }
 | 
			
		||||
     $do_spdy && { run_spdy; ret=$(($? + ret)); }
 | 
			
		||||
     $do_http2 && { run_http2; ret=$(($? + ret)); }
 | 
			
		||||
 | 
			
		||||
     fileout_section_header $section_number true && ((section_number++))
 | 
			
		||||
     $do_std_cipherlists && { run_std_cipherlists; ret=$(($? + ret)); }
 | 
			
		||||
 | 
			
		||||
     fileout_section_header $section_number true && ((section_number++))
 | 
			
		||||
     $do_pfs && { run_pfs; ret=$(($? + ret)); }
 | 
			
		||||
 | 
			
		||||
     fileout_section_header $section_number true && ((section_number++))
 | 
			
		||||
     $do_server_preference && { run_server_preference; ret=$(($? + ret)); }
 | 
			
		||||
 | 
			
		||||
     fileout_section_header $section_number true && ((section_number++))
 | 
			
		||||
     $do_server_defaults && { run_server_defaults; ret=$(($? + ret)); }
 | 
			
		||||
 | 
			
		||||
     if $do_header; then
 | 
			
		||||
          #TODO: refactor this into functions
 | 
			
		||||
          fileout_section_header $section_number true && ((section_number++))
 | 
			
		||||
          if [[ $SERVICE == "HTTP" ]]; then
 | 
			
		||||
               run_http_header "$URL_PATH"
 | 
			
		||||
               run_http_date "$URL_PATH"
 | 
			
		||||
@@ -9773,6 +9947,8 @@ lets_roll() {
 | 
			
		||||
               run_more_flags "$URL_PATH"
 | 
			
		||||
               run_rp_banner "$URL_PATH"
 | 
			
		||||
         fi
 | 
			
		||||
     else
 | 
			
		||||
         ((section_number++))
 | 
			
		||||
     fi
 | 
			
		||||
 | 
			
		||||
     # vulnerabilities
 | 
			
		||||
@@ -9780,6 +9956,8 @@ lets_roll() {
 | 
			
		||||
          outln; pr_headlineln " Testing vulnerabilities "
 | 
			
		||||
          outln
 | 
			
		||||
     fi
 | 
			
		||||
 | 
			
		||||
     fileout_section_header $section_number true && ((section_number++))
 | 
			
		||||
     $do_heartbleed && { run_heartbleed; ret=$(($? + ret)); }
 | 
			
		||||
     $do_ccs_injection && { run_ccs_injection; ret=$(($? + ret)); }
 | 
			
		||||
     $do_renego && { run_renego; ret=$(($? + ret)); }
 | 
			
		||||
@@ -9793,11 +9971,17 @@ lets_roll() {
 | 
			
		||||
     $do_beast && { run_beast; ret=$(($? + ret)); }
 | 
			
		||||
     $do_rc4 && { run_rc4; ret=$(($? + ret)); }
 | 
			
		||||
 | 
			
		||||
     fileout_section_header $section_number true && ((section_number++))
 | 
			
		||||
     $do_allciphers && { run_allciphers; ret=$(($? + ret)); }
 | 
			
		||||
     $do_cipher_per_proto && { run_cipher_per_proto; ret=$(($? + ret)); }
 | 
			
		||||
 | 
			
		||||
     fileout_section_header $section_number true && ((section_number++))
 | 
			
		||||
     $do_client_simulation && { run_client_simulation; ret=$(($? + ret)); }
 | 
			
		||||
 | 
			
		||||
     fileout_section_footer
 | 
			
		||||
 | 
			
		||||
     outln
 | 
			
		||||
     END_TIME=$(date +%s)
 | 
			
		||||
     datebanner " Done"
 | 
			
		||||
 | 
			
		||||
     return $ret
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user