mirror of
				https://github.com/drwetter/testssl.sh.git
				synced 2025-10-30 21:35:26 +01:00 
			
		
		
		
	Merge branch '2.9dev' of github.com:drwetter/testssl.sh into 2.9dev
This commit is contained in:
		
							
								
								
									
										188
									
								
								testssl.sh
									
									
									
									
									
								
							
							
						
						
									
										188
									
								
								testssl.sh
									
									
									
									
									
								
							| @@ -4660,6 +4660,80 @@ pr_ecdh_curve_quality() { | |||||||
|      fi |      fi | ||||||
| } | } | ||||||
|  |  | ||||||
|  | # Print $2 based on the quality of the cipher in $1. If $2 is empty, print $1. | ||||||
|  | # The return value is an indicator of the quality of the cipher in $1: | ||||||
|  | #   0 = $1 is empty | ||||||
|  | #   1 = pr_svrty_critical, 2 = pr_svrty_high, 3 = pr_svrty_medium, 4 = pr_svrty_low | ||||||
|  | #   5 = neither good nor bad, 6 = pr_done_good, 7 = pr_done_best  | ||||||
|  | pr_cipher_quality() { | ||||||
|  |      local cipher="$1" | ||||||
|  |      local text="$2" | ||||||
|  |  | ||||||
|  |      [[ -z "$1" ]] && return 0 | ||||||
|  |      [[ -z "$text" ]] && text="$cipher" | ||||||
|  |       | ||||||
|  |      if [[ "$cipher" != TLS_* ]] && [[ "$cipher" != SSL_* ]]; then | ||||||
|  |           # This must be the OpenSSL name for a cipher | ||||||
|  |           if [[ $TLS_NR_CIPHERS -eq 0 ]]; then | ||||||
|  |                # We have the OpenSSL name and can't convert it to the RFC name | ||||||
|  |                case "$cipher" in | ||||||
|  |                     *NULL*|*EXP*) | ||||||
|  |                          pr_svrty_critical "$text" | ||||||
|  |                          return 1 | ||||||
|  |                          ;; | ||||||
|  |                     *RC4*) | ||||||
|  |                          pr_svrty_high "$text" | ||||||
|  |                          return 2 | ||||||
|  |                          ;; | ||||||
|  |                     *CBC*) | ||||||
|  |                          pr_svrty_medium "$text" | ||||||
|  |                          return 3 | ||||||
|  |                          ;; # FIXME BEAST: We miss some CBC ciphers here, need to work w/ a list | ||||||
|  |                     *GCM*|*CHACHA20*) | ||||||
|  |                          pr_done_best "$text" | ||||||
|  |                          return 7 | ||||||
|  |                          ;; #best ones | ||||||
|  |                     ECDHE*AES*) | ||||||
|  |                          pr_svrty_low "$text" | ||||||
|  |                          return 4 | ||||||
|  |                          ;; # it's CBC. --> lucky13 | ||||||
|  |                     *) | ||||||
|  |                          out "$text" | ||||||
|  |                          return 5 | ||||||
|  |                          ;; | ||||||
|  |                esac | ||||||
|  |           fi | ||||||
|  |           cipher="$(openssl2rfc "$cipher")" | ||||||
|  |      fi | ||||||
|  |  | ||||||
|  |      case "$cipher" in | ||||||
|  |           *NULL*|*EXP*|*RC2*|*_DES_*|*_DES40_*) | ||||||
|  |                pr_svrty_critical "$text" | ||||||
|  |                return 1 | ||||||
|  |                ;; | ||||||
|  |           *RC4*) | ||||||
|  |                pr_svrty_high "$text" | ||||||
|  |                return 2 | ||||||
|  |                ;; | ||||||
|  |           *ECDHE*AES*CBC*) | ||||||
|  |                pr_svrty_low "$text" | ||||||
|  |                return 4 | ||||||
|  |                ;; | ||||||
|  |           *CBC*) | ||||||
|  |                pr_svrty_medium "$text" | ||||||
|  |                return 3 | ||||||
|  |                ;; | ||||||
|  |           *GCM*|*CHACHA20*) | ||||||
|  |                pr_done_best "$text" | ||||||
|  |                return 7 | ||||||
|  |                ;; | ||||||
|  |           *) | ||||||
|  |                out "$text" | ||||||
|  |                return 5 | ||||||
|  |                ;; | ||||||
|  |      esac | ||||||
|  | } | ||||||
|  |  | ||||||
| # arg1: file with input for grepping the bit length for ECDH/DHE | # arg1: file with input for grepping the bit length for ECDH/DHE | ||||||
| # arg2: whether to print warning "old fart" or not (empty: no) | # arg2: whether to print warning "old fart" or not (empty: no) | ||||||
| read_dhbits_from_file() { | read_dhbits_from_file() { | ||||||
| @@ -4876,28 +4950,24 @@ run_server_preference() { | |||||||
|                default_cipher="$(openssl2rfc "$default_cipher_ossl")" |                default_cipher="$(openssl2rfc "$default_cipher_ossl")" | ||||||
|                [[ -z "$default_cipher" ]] && default_cipher="$default_cipher_ossl" |                [[ -z "$default_cipher" ]] && default_cipher="$default_cipher_ossl" | ||||||
|           fi |           fi | ||||||
|           case "$default_cipher_ossl" in |           pr_cipher_quality "$default_cipher" | ||||||
|                *NULL*|*EXP*) |           case $? in | ||||||
|                     pr_svrty_critical "$default_cipher" |                1) | ||||||
|                     fileout "order_cipher" "CRITICAL" "Default cipher: $default_cipher$(read_dhbits_from_file "$TMPFILE") $remark4default_cipher" |                     fileout "order_cipher" "CRITICAL" "Default cipher: $default_cipher$(read_dhbits_from_file "$TMPFILE") $remark4default_cipher" | ||||||
|                     ;; |                     ;; | ||||||
|                *RC4*) |                2) | ||||||
|                     pr_svrty_high "$default_cipher" |  | ||||||
|                     fileout "order_cipher" "HIGH" "Default cipher: $default_cipher$(read_dhbits_from_file "$TMPFILE") $remark4default_cipher" |                     fileout "order_cipher" "HIGH" "Default cipher: $default_cipher$(read_dhbits_from_file "$TMPFILE") $remark4default_cipher" | ||||||
|                     ;; |                     ;; | ||||||
|                *CBC*) |                3) | ||||||
|                     pr_svrty_medium "$default_cipher" |  | ||||||
|                     fileout "order_cipher" "MEDIUM" "Default cipher: $default_cipher$(read_dhbits_from_file "$TMPFILE") $remark4default_cipher" |                     fileout "order_cipher" "MEDIUM" "Default cipher: $default_cipher$(read_dhbits_from_file "$TMPFILE") $remark4default_cipher" | ||||||
|                     ;;   # FIXME BEAST: We miss some CBC ciphers here, need to work w/ a list |                     ;; | ||||||
|                *GCM*|*CHACHA20*) |                6|7) | ||||||
|                     pr_done_best "$default_cipher" |  | ||||||
|                     fileout "order_cipher" "OK" "Default cipher: $default_cipher$(read_dhbits_from_file "$TMPFILE") $remark4default_cipher" |                     fileout "order_cipher" "OK" "Default cipher: $default_cipher$(read_dhbits_from_file "$TMPFILE") $remark4default_cipher" | ||||||
|                     ;;   # best ones |                     ;;   # best ones | ||||||
|                ECDHE*AES*) |                4) | ||||||
|                     pr_svrty_low "$default_cipher" |  | ||||||
|                     fileout "order_cipher" "LOW" "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 |                     ;;  # it's CBC. --> lucky13 | ||||||
|                "") |                0) | ||||||
|                     pr_warning "default cipher empty" ; |                     pr_warning "default cipher empty" ; | ||||||
|                     if [[ $OSSL_VER == 1.0.2* ]]; then |                     if [[ $OSSL_VER == 1.0.2* ]]; then | ||||||
|                          out " (Hint: if IIS6 give OpenSSL 1.0.1 a try)" |                          out " (Hint: if IIS6 give OpenSSL 1.0.1 a try)" | ||||||
| @@ -4907,7 +4977,6 @@ run_server_preference() { | |||||||
|                     fi |                     fi | ||||||
|                     ;; |                     ;; | ||||||
|                *) |                *) | ||||||
|                     out "$default_cipher" |  | ||||||
|                     fileout "order_cipher" "INFO" "Default cipher: $default_cipher$(read_dhbits_from_file "$TMPFILE")  $remark4default_cipher" |                     fileout "order_cipher" "INFO" "Default cipher: $default_cipher$(read_dhbits_from_file "$TMPFILE")  $remark4default_cipher" | ||||||
|                     ;; |                     ;; | ||||||
|           esac |           esac | ||||||
| @@ -5894,6 +5963,50 @@ compare_server_name_to_cert() | |||||||
|      return $ret |      return $ret | ||||||
| } | } | ||||||
|  |  | ||||||
|  | must_staple() { | ||||||
|  |      local json_prefix="$2" | ||||||
|  |      local cert extn | ||||||
|  |      local -i extn_len | ||||||
|  |      local supported=false | ||||||
|  |       | ||||||
|  |      # Note this function is only looking for status_request (5) and not | ||||||
|  |      # status_request_v2 (17), since OpenSSL seems to only include status_request (5) | ||||||
|  |      # in its ClientHello when the "-status" option is used. | ||||||
|  |       | ||||||
|  |      # OpenSSL 1.1.0 supports pretty-printing the "TLS Feature extension." For any | ||||||
|  |      # previous versions of OpenSSL, OpenSSL can only show if the extension OID is present. | ||||||
|  |      if $OPENSSL x509 -in "$HOSTCERT" -noout -text 2>>$ERRFILE | grep -A 1 "TLS Feature:" | grep -q "status_request"; then | ||||||
|  |           # FIXME: This will indicate that must staple is supported if the | ||||||
|  |           # certificate indicates status_request or status_request_v2. This is | ||||||
|  |           # probably okay, since it seems likely that any TLS Feature extension | ||||||
|  |           # that includes status_request_v2 will also include status_request. | ||||||
|  |           supported=true | ||||||
|  |      elif $OPENSSL x509 -in "$HOSTCERT" -noout -text 2>>$ERRFILE | grep -q "1.3.6.1.5.5.7.1.24:"; then | ||||||
|  |           cert="$($OPENSSL x509 -in "$HOSTCERT" -outform DER 2>>$ERRFILE | hexdump -v -e '16/1 "%02X"')" | ||||||
|  |           extn="${cert##*06082B06010505070118}" | ||||||
|  |           # Check for critical bit, and skip over it if present. | ||||||
|  |           [[ "${extn:0:6}" == "0101FF" ]] && extn="${extn:6}" | ||||||
|  |           # Next is tag and length of extnValue OCTET STRING. Assume it is less than 128 bytes. | ||||||
|  |           extn="${extn:4}" | ||||||
|  |           # The TLS Feature is a SEQUENCE of INTEGER. Get the length of the SEQUENCE | ||||||
|  |           extn_len=2*$(hex2dec "${extn:2:2}") | ||||||
|  |           # If the extension include the status_request (5), then it supports must staple. | ||||||
|  |           if [[ "${extn:4:extn_len}" =~ "020105" ]]; then | ||||||
|  |                supported=true | ||||||
|  |           fi | ||||||
|  |      fi | ||||||
|  |  | ||||||
|  |      if "$supported"; then | ||||||
|  |           pr_done_bestln "Supported" | ||||||
|  |           fileout "${json_prefix}ocsp_must_staple" "OK" "OCSP must staple : supported" | ||||||
|  |           return 0 | ||||||
|  |      else | ||||||
|  |           outln "No" | ||||||
|  |           fileout "${json_prefix}ocsp_must_staple" "INFO" "OCSP must staple : no" | ||||||
|  |           return 1 | ||||||
|  |      fi | ||||||
|  | } | ||||||
|  |  | ||||||
| certificate_info() { | certificate_info() { | ||||||
|      local proto |      local proto | ||||||
|      local -i certificate_number=$1 |      local -i certificate_number=$1 | ||||||
| @@ -5904,7 +6017,8 @@ certificate_info() { | |||||||
|      local ocsp_response_status=$6 |      local ocsp_response_status=$6 | ||||||
|      local sni_used=$7 |      local sni_used=$7 | ||||||
|      local cert_sig_algo cert_sig_hash_algo cert_key_algo |      local cert_sig_algo cert_sig_hash_algo cert_key_algo | ||||||
|      local expire days2expire secs2warn ocsp_uri crl startdate enddate issuer_CN issuer_C issuer_O issuer sans san all_san="" cn |      local expire days2expire secs2warn ocsp_uri ocsp_must_staple crl | ||||||
|  |      local startdate enddate issuer_CN issuer_C issuer_O issuer sans san all_san="" cn | ||||||
|      local issuer_DC issuerfinding cn_nosni="" |      local issuer_DC issuerfinding cn_nosni="" | ||||||
|      local cert_fingerprint_sha1 cert_fingerprint_sha2 cert_fingerprint_serial |      local cert_fingerprint_sha1 cert_fingerprint_sha2 cert_fingerprint_serial | ||||||
|      local policy_oid |      local policy_oid | ||||||
| @@ -6423,10 +6537,22 @@ certificate_info() { | |||||||
|           fileout "${json_prefix}ocsp_uri" "INFO" "OCSP URI : $ocsp_uri" |           fileout "${json_prefix}ocsp_uri" "INFO" "OCSP URI : $ocsp_uri" | ||||||
|      fi |      fi | ||||||
|  |  | ||||||
|  |      out "$indent"; pr_bold " OCSP must staple             "; | ||||||
|  |      must_staple "$json_prefix" | ||||||
|  |      [[ $? -eq 0 ]] && ocsp_must_staple=true || ocsp_must_staple=false | ||||||
|  |  | ||||||
|      out "$indent"; pr_bold " OCSP stapling                " |      out "$indent"; pr_bold " OCSP stapling                " | ||||||
|      if grep -a "OCSP response" <<<"$ocsp_response" | grep -q "no response sent" ; then |      if grep -a "OCSP response" <<<"$ocsp_response" | grep -q "no response sent" ; then | ||||||
|  |           if "$ocsp_must_staple"; then | ||||||
|  |                pr_svrty_critical "--" | ||||||
|  |                fileout "${json_prefix}ocsp_stapling" "CRITICAL" "OCSP stapling : not offered" | ||||||
|  |           elif [[ -n "$ocsp_uri" ]]; then | ||||||
|                pr_svrty_low "--" |                pr_svrty_low "--" | ||||||
|                fileout "${json_prefix}ocsp_stapling" "LOW" "OCSP stapling : not offered" |                fileout "${json_prefix}ocsp_stapling" "LOW" "OCSP stapling : not offered" | ||||||
|  |           else | ||||||
|  |                out "--" | ||||||
|  |                fileout "${json_prefix}ocsp_stapling" "INFO" "OCSP stapling : not offered" | ||||||
|  |           fi | ||||||
|      else |      else | ||||||
|           if grep -a "OCSP Response Status" <<<"$ocsp_response_status" | grep -q successful; then |           if grep -a "OCSP Response Status" <<<"$ocsp_response_status" | grep -q successful; then | ||||||
|                pr_done_good "offered" |                pr_done_good "offered" | ||||||
| @@ -9350,9 +9476,6 @@ run_ccs_injection(){ | |||||||
|      if [[ $DEBUG -ge 3 ]]; then |      if [[ $DEBUG -ge 3 ]]; then | ||||||
|           outln "\n1st reply: " |           outln "\n1st reply: " | ||||||
|           hexdump -C "$SOCK_REPLY_FILE" | head -20 |           hexdump -C "$SOCK_REPLY_FILE" | head -20 | ||||||
| # ok:      15 | 0301    |  02 | 02 | 0a |  | ||||||
| #       ALERT | TLS 1.0 | Length=2 | Unexpected Message (0a) |  | ||||||
| #    or just timed out |  | ||||||
|           outln |           outln | ||||||
|           out "sending payload #2 with TLS version $tls_hexcode:  " |           out "sending payload #2 with TLS version $tls_hexcode:  " | ||||||
|      fi |      fi | ||||||
| @@ -9372,29 +9495,38 @@ run_ccs_injection(){ | |||||||
|           outln |           outln | ||||||
|      fi |      fi | ||||||
|  |  | ||||||
| # not ok:  15 | 0301    | 02 | 02  | 15 | # in general, see https://en.wikipedia.org/wiki/Transport_Layer_Security#Alert_protocol | ||||||
|  | #                 https://tools.ietf.org/html/rfc5246#section-7.2 | ||||||
|  | # | ||||||
|  | # not ok fo CCSI:  15 | 0301    | 00 02    | 02 15 | ||||||
| #               ALERT | TLS 1.0 | Length=2 | Decryption failed (21) | #               ALERT | TLS 1.0 | Length=2 | Decryption failed (21) | ||||||
| # | # | ||||||
| # ok:  0a or nothing: ==> RST | # ok:   nothing: ==> RST | ||||||
|  | # | ||||||
|  | # 0A:      Unexpected message | ||||||
|  | # 28:      Handshake failure | ||||||
|      if [[ -z "${tls_hello_ascii:0:12}" ]]; then |      if [[ -z "${tls_hello_ascii:0:12}" ]]; then | ||||||
|           # empty reply |           # empty reply | ||||||
|           pr_done_best "not vulnerable (OK)" |           pr_done_best "not vulnerable (OK)" | ||||||
|           if [[ $retval -eq 3 ]]; then |           if [[ $retval -eq 3 ]]; then | ||||||
| ### what? |  | ||||||
|                fileout "ccs" "OK" "CCS: not vulnerable (timed out)" "$cve" "$cwe" |                fileout "ccs" "OK" "CCS: not vulnerable (timed out)" "$cve" "$cwe" | ||||||
|           else |           else | ||||||
|                fileout "ccs" "OK" "CCS: not vulnerable" "$cve" "$cwe" |                fileout "ccs" "OK" "CCS: not vulnerable" "$cve" "$cwe" | ||||||
|           fi |           fi | ||||||
|           ret=0 |           ret=0 | ||||||
|      elif [[ "$byte6" == "15" ]] && [[ "${tls_hello_ascii:0:4}" == "1503" ]]; then |      elif [[ "$byte6" == "15" ]] && [[ "${tls_hello_ascii:0:4}" == "1503" ]]; then | ||||||
|  |           # decyption failed received | ||||||
|           pr_svrty_critical "VULNERABLE (NOT ok)" |           pr_svrty_critical "VULNERABLE (NOT ok)" | ||||||
|           if [[ $retval -eq 3 ]]; then |  | ||||||
|                fileout "ccs" "CRITICAL" "CCS: VULNERABLE (timed out)" "$cve" "$cwe" "$hint" |  | ||||||
|           else |  | ||||||
|           fileout "ccs" "CRITICAL" "CCS: VULNERABLE" "$cve" "$cwe" "$hint" |           fileout "ccs" "CRITICAL" "CCS: VULNERABLE" "$cve" "$cwe" "$hint" | ||||||
|           fi |  | ||||||
|           ret=1 |           ret=1 | ||||||
|  |      elif [[ "${tls_hello_ascii:0:4}" == "1503" ]]; then | ||||||
|  |           if [[ "$byte6" == "0A" ]] || [[ "$byte6" == "28" ]]; then | ||||||
|  |                # Unexpected message / Handshake failure  received | ||||||
|  |                pr_warning "likely " | ||||||
|  |                out "not vulnerable (OK)" | ||||||
|  |                out " - alert description type: $byte6" | ||||||
|  |                fileout "ccs" "WARN" "CCS: probably not vulnerable but received 0x${byte6} instead of 0x15" "$cve" "$cwe" "$hint" | ||||||
|  |           fi | ||||||
|      elif [[ "$byte6" == [0-9a-f][0-9a-f] ]] && [[ "${tls_hello_ascii:2:2}" != "03" ]]; then |      elif [[ "$byte6" == [0-9a-f][0-9a-f] ]] && [[ "${tls_hello_ascii:2:2}" != "03" ]]; then | ||||||
|           pr_warning "test failed" |           pr_warning "test failed" | ||||||
|           out ", probably read buffer too small (${tls_hello_ascii:0:14})" |           out ", probably read buffer too small (${tls_hello_ascii:0:14})" | ||||||
| @@ -9402,8 +9534,8 @@ run_ccs_injection(){ | |||||||
|           ret=7 |           ret=7 | ||||||
|      else |      else | ||||||
|           pr_warning "test failed " |           pr_warning "test failed " | ||||||
|           out "around line $LINENO (debug info: ${tls_hello_ascii:0:14})" |           out "around line $LINENO (debug info: ${tls_hello_ascii:0:12},$byte6)" | ||||||
|           fileout "ccs" "WARN" "CCS: test failed, around line $LINENO, debug info (${tls_hello_ascii:0:14})" "$cve" "$cwe" "$hint" |           fileout "ccs" "WARN" "CCS: test failed, around line $LINENO, debug info (${tls_hello_ascii:0:12},$byte6)" "$cve" "$cwe" "$hint" | ||||||
|           ret=7 |           ret=7 | ||||||
|      fi |      fi | ||||||
|      outln |      outln | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Dirk
					Dirk