@@ -3370,7 +3370,7 @@ run_cookie_flags() { # ARG1: Path
33703370 fi
33713371
33723372 if [[ ! "$HTTP_STATUS_CODE" =~ 20 ]]; then
3373- if [[ "$HTTP_STATUS_CODE" =~ [ 301|302] ]]; then
3373+ if [[ "$HTTP_STATUS_CODE" =~ 301|302 ]]; then
33743374 msg302=" -- maybe better try target URL of 30x"
33753375 msg302_=" (30x detected, better try target URL of 30x)"
33763376 else
@@ -9637,13 +9637,15 @@ certificate_info() {
96379637 jsonID="cert_certificatePolicies_EV"
96389638 # only the first one, seldom we have two
96399639 policy_oid=$(awk '/ .Policy: / { print $2 }' <<< "$cert_txt" | awk 'NR < 2')
9640- if grep -Eq 'Extended Validation|Extended Validated|EV SSL|EV CA' <<< "$issuer" || \
9640+ if grep -Eq 'Extended Validation|Extended Validated|EV SSL|EV CA|EV TLS' <<< "$issuer" || \
9641+ [[ 2.23.140.1.1 == "$policy_oid" ]] || \
96419642 [[ 2.16.840.1.114028.10.1.2 == "$policy_oid" ]] || \
96429643 [[ 2.16.840.1.114412.1.3.0.2 == "$policy_oid" ]] || \
96439644 [[ 2.16.840.1.114412.2.1 == "$policy_oid" ]] || \
96449645 [[ 2.16.578.1.26.1.3.3 == "$policy_oid" ]] || \
96459646 [[ 1.3.6.1.4.1.17326.10.14.2.1.2 == "$policy_oid" ]] || \
96469647 [[ 1.3.6.1.4.1.17326.10.8.12.1.2 == "$policy_oid" ]] || \
9648+ [[ 1.3.6.1.4.1.38064.1.3.1.4 == "$policy_oid" ]] || \
96479649 [[ 1.3.6.1.4.1.13177.10.1.3.10 == "$policy_oid" ]] ; then
96489650 out "yes "
96499651 fileout "${jsonID}${json_postfix}" "OK" "yes"
@@ -10926,6 +10928,40 @@ run_fs() {
1092610928 [[ $i -eq $high ]] && break
1092710929 supported_curve[i]=true
1092810930 done
10931+ # Versions of TLS prior to 1.3 close the connection if the client does not support the curve
10932+ # used in the certificate. The easiest solution is to move the curves to the end of the list.
10933+ # instead of removing them from the ClientHello. This is only needed if there is no RSA certificate.
10934+ if { ! "$HAS_TLS13" || [[ "$proto" == "-no_tls1_3" ]]; } && [[ ! "$ecdhe_cipher_list" == *RSA* ]]; then
10935+ while true; do
10936+ curves_to_test=""
10937+ for (( i=low; i < high; i++ )); do
10938+ "${ossl_supported[i]}" && ! "${supported_curve[i]}" && curves_to_test+=":${curves_ossl[i]}"
10939+ done
10940+ [[ -z "$curves_to_test" ]] && break
10941+ for (( i=low; i < high; i++ )); do
10942+ "${supported_curve[i]}" && curves_to_test+=":${curves_ossl[i]}"
10943+ done
10944+ $OPENSSL s_client $(s_client_options "$proto -cipher "\'${ecdhe_cipher_list:1}\'" -ciphersuites "\'${tls13_cipher_list:1}\'" -curves "${curves_to_test:1}" $STARTTLS $BUGS -connect $NODEIP:$PORT $PROXY $SNI") &>$TMPFILE </dev/null
10945+ sclient_connect_successful $? $TMPFILE || break
10946+ temp=$(awk -F': ' '/^Server Temp Key/ { print $2 }' "$TMPFILE")
10947+ curve_found="${temp%%,*}"
10948+ if [[ "$curve_found" == ECDH ]]; then
10949+ curve_found="${temp#*, }"
10950+ curve_found="${curve_found%%,*}"
10951+ if "$HAS_TLS13" && [[ ! "$proto" == "-no_tls1_3" ]] && [[ "$curve_found" == brainpoolP[235][581][642]r1 ]]; then
10952+ [[ "$(get_protocol "$TMPFILE")" == TLSv1.3 ]] && curve_found+="tls13"
10953+ fi
10954+ fi
10955+ for (( i=low; i < high; i++ )); do
10956+ if ! "${supported_curve[i]}"; then
10957+ [[ "${curves_ossl_output[i]}" == "$curve_found" ]] && break
10958+ [[ "${curves_ossl[i]}" == "$curve_found" ]] && break
10959+ fi
10960+ done
10961+ [[ $i -eq $high ]] && break
10962+ supported_curve[i]=true
10963+ done
10964+ fi
1092910965 done
1093010966 done
1093110967 fi
@@ -10962,6 +10998,37 @@ run_fs() {
1096210998 [[ $i -eq $nr_curves ]] && break
1096310999 supported_curve[i]=true
1096411000 done
11001+ # Versions of TLS prior to 1.3 close the connection if the client does not support the curve
11002+ # used in the certificate. The easiest solution is to move the curves to the end of the list.
11003+ # instead of removing them from the ClientHello. This is only needed if there is no RSA certificate.
11004+ if [[ "$proto" == 03 ]] && [[ ! "$ecdhe_cipher_list" == *RSA* ]]; then
11005+ while true; do
11006+ curves_to_test=""
11007+ for (( i=0; i < nr_curves; i++ )); do
11008+ ! "${supported_curve[i]}" && curves_to_test+=", ${curves_hex[i]}"
11009+ done
11010+ [[ -z "$curves_to_test" ]] && break
11011+ for (( i=0; i < nr_curves; i++ )); do
11012+ "${supported_curve[i]}" && curves_to_test+=", ${curves_hex[i]}"
11013+ done
11014+ len1=$(printf "%02x" "$((2*${#curves_to_test}/7))")
11015+ len2=$(printf "%02x" "$((2*${#curves_to_test}/7+2))")
11016+ tls_sockets "$proto" "${ecdhe_cipher_list_hex:2}, 00,ff" "ephemeralkey" "00, 0a, 00, $len2, 00, $len1, ${curves_to_test:2}"
11017+ sclient_success=$?
11018+ [[ $sclient_success -ne 0 ]] && [[ $sclient_success -ne 2 ]] && break
11019+ temp=$(awk -F': ' '/^Server Temp Key/ { print $2 }' "$TEMPDIR/$NODEIP.parse_tls_serverhello.txt")
11020+ curve_found="${temp%%,*}"
11021+ if [[ "$curve_found" == "ECDH" ]]; then
11022+ curve_found="${temp#*, }"
11023+ curve_found="${curve_found%%,*}"
11024+ fi
11025+ for (( i=0; i < nr_curves; i++ )); do
11026+ ! "${supported_curve[i]}" && [[ "${curves_ossl_output[i]}" == "$curve_found" ]] && break
11027+ done
11028+ [[ $i -eq $nr_curves ]] && break
11029+ supported_curve[i]=true
11030+ done
11031+ fi
1096511032 done
1096611033 fi
1096711034 if "$ecdhe_offered"; then
@@ -11253,7 +11320,7 @@ npn_pre(){
1125311320 fileout "NPN" "WARN" "not tested as proxies do not support proxying it"
1125411321 return 1
1125511322 fi
11256- if ! "$HAS_NPN"; then
11323+ if "$SSL_NATIVE" && ! "$HAS_NPN"; then
1125711324 pr_local_problem "$OPENSSL doesn't support NPN/SPDY";
1125811325 fileout "NPN" "WARN" "not tested $OPENSSL doesn't support NPN/SPDY"
1125911326 return 7
@@ -11299,20 +11366,31 @@ run_npn() {
1129911366 return 0
1130011367 fi
1130111368
11302- # TLS 1.3 s_client doesn't support -nextprotoneg when connecting with TLS 1.3. So we need to make sure it won't be used
11303- # TLS13_ONLY is tested here again, just to be sure, see npn_pre
11304- if "$HAS_TLS13" && ! $TLS13_ONLY ]] ; then
11305- proto="-no_tls1_3"
11369+ if "$HAS_NPN"; then
11370+ # TLS 1.3 s_client doesn't support -nextprotoneg when connecting with TLS 1.3. So we need to make sure it won't be used
11371+ # TLS13_ONLY is tested here again, just to be sure, see npn_pre
11372+ if "$HAS_TLS13" && ! $TLS13_ONLY ]] ; then
11373+ proto="-no_tls1_3"
11374+ fi
11375+ $OPENSSL s_client $(s_client_options "$proto -connect $NODEIP:$PORT $BUGS $SNI -nextprotoneg "$NPN_PROTOs"") </dev/null 2>$ERRFILE >$TMPFILE
11376+ [[ $? -ne 0 ]] && ret=1
11377+ else
11378+ tls_sockets "03" "$TLS12_CIPHER" "all"
11379+ ret=$?
11380+ if [[ $ret -eq 0 ]] || [[ $ret -eq 2 ]]; then
11381+ ret=0
11382+ else
11383+ ret=1
11384+ fi
11385+ mv "$TEMPDIR/$NODEIP.parse_tls_serverhello.txt" "$TMPFILE"
1130611386 fi
11307- $OPENSSL s_client $(s_client_options "$proto -connect $NODEIP:$PORT $BUGS $SNI -nextprotoneg "$NPN_PROTOs"") </dev/null 2>$ERRFILE >$TMPFILE
11308- [[ $? -ne 0 ]] && ret=1
1130911387 tmpstr="$(grep -a '^Protocols' $TMPFILE | sed 's/Protocols.*: //')"
1131011388 if [[ -z "$tmpstr" ]] || [[ "$tmpstr" == " " ]]; then
1131111389 outln "not offered"
1131211390 fileout "$jsonID" "INFO" "not offered"
1131311391 else
1131411392 # now comes a strange thing: "Protocols advertised by server:" is empty but connection succeeded
11315- if [[ "$tmpstr" =~ [ h2|spdy|http] ]]; then
11393+ if [[ "$tmpstr" =~ h2|spdy|http ]]; then
1131611394 out "$tmpstr"
1131711395 outln " (advertised)"
1131811396 fileout "$jsonID" "INFO" "offered with $tmpstr (advertised)"
@@ -16854,7 +16932,7 @@ run_ccs_injection(){
1685416932 fileout "$jsonID" "OK" "not vulnerable" "$cve" "$cwe"
1685516933 fi
1685616934 elif [[ "${tls_hello_ascii:0:4}" == "1503" ]]; then
16857- if [[ ! "${tls_hello_ascii:5:2}" =~ [ 03|02|01|00] ]]; then
16935+ if [[ ! "${tls_hello_ascii:5:2}" =~ 03|02|01|00 ]]; then
1685816936 pr_warning "test failed "
1685916937 out "no proper TLS reply (debug info: protocol sent: 1503${tls_hexcode#x03, x}, reply: ${tls_hello_ascii:0:14}"
1686016938 fileout "$jsonID" "DEBUG" "test failed, around line $LINENO, debug info (${tls_hello_ascii:0:14})" "$cve" "$cwe" "$hint"
@@ -16907,25 +16985,11 @@ run_ccs_injection(){
1690716985 return $ret
1690816986}
1690916987
16910- sub_session_ticket_tls() {
16911- local tls_proto="$1"
16912- local sessticket_tls=""
16913- #FIXME: we likely have done this already before (either @ run_server_defaults() or at least the output
16914- # from a previous handshake) --> would save 1x connect. We have TLS_TICKET but not yet the ticket itself #FIXME
16915- #ATTENTION: we DO NOT use SNI here as we assume ticketbleed is a vulnerability of the TLS stack. If we'd do SNI here, we'd also need
16916- # it in the ClientHello of run_ticketbleed() otherwise the ticket will be different and the whole thing won't work!
16917- #
16918- sessticket_tls="$($OPENSSL s_client $(s_client_options "$BUGS $tls_proto $PROXY $SNI -connect $NODEIP:$PORT") </dev/null 2>$ERRFILE | awk '/TLS session ticket:/,/^$/' | awk '!/TLS session ticket/')"
16919- sessticket_tls="$(sed -e 's/^.* - /x/g' -e 's/ .*$//g' <<< "$sessticket_tls" | tr '\n' ',')"
16920- sed -e 's/ /,x/g' -e 's/-/,x/g' <<< "$sessticket_tls"
16921-
16922- }
16923-
1692416988
1692516989# see https://blog.filippo.io/finding-ticketbleed/ | https://filippo.io/ticketbleed/
1692616990run_ticketbleed() {
1692716991 local tls_hexcode tls_proto=""
16928- local session_tckt_tls=""
16992+ local sessticket_tls="" session_tckt_tls=""
1692916993 local -i len_ch=300 # fixed len of prepared clienthello below
1693016994 local sid="x00,x0B,xAD,xC0,xDE,x00," # some arbitrary bytes
1693116995 local len_sid="$(( ${#sid} / 4))"
@@ -16961,27 +17025,50 @@ run_ticketbleed() {
1696117025 return 0
1696217026 fi
1696317027
16964- if [[ 0 -eq $(has_server_protocol tls1 ) ]]; then
16965- tls_hexcode="x03, x01 "; tls_proto="-tls1 "
17028+ if [[ 0 -eq $(has_server_protocol tls1_2 ) ]]; then
17029+ tls_hexcode="x03, x03 "; tls_proto="-tls1_2 "
1696617030 elif [[ 0 -eq $(has_server_protocol tls1_1) ]]; then
1696717031 tls_hexcode="x03, x02"; tls_proto="-tls1_1"
16968- elif [[ 0 -eq $(has_server_protocol tls1_2 ) ]]; then
16969- tls_hexcode="x03, x03 "; tls_proto="-tls1_2 "
17032+ elif [[ 0 -eq $(has_server_protocol tls1 ) ]]; then
17033+ tls_hexcode="x03, x01 "; tls_proto="-tls1 "
1697017034 elif [[ 0 -eq $(has_server_protocol ssl3) ]]; then
1697117035 tls_hexcode="x03, x00"; tls_proto="-ssl3"
1697217036 else # no protocol for some reason defined, determine TLS versions offered with a new handshake
1697317037 "$HAS_TLS13" && tls_proto="-no_tls1_3"
1697417038 $OPENSSL s_client $(s_client_options "$STARTTLS $BUGS $tls_proto -connect $NODEIP:$PORT $PROXY") >$TMPFILE 2>$ERRFILE </dev/null
17039+ sclient_connect_successful $? "$TMPFILE"
17040+ if [[ $? -ne 0 ]]; then
17041+ prln_warning "Cannot test for ticketbleed. Your OpenSSL cannot connect to $NODEIP:$PORT"
17042+ fileout "$jsonID" "WARN" "Cannot test for ticketbleed. Your OpenSSL cannot connect to $NODEIP:$PORT."
17043+ return 1
17044+ fi
1697517045 case "$(get_protocol $TMPFILE)" in
1697617046 *1.2) tls_hexcode="x03, x03"; tls_proto="-tls1_2" ; add_proto_offered tls1_2 yes ;;
1697717047 *1.1) tls_hexcode="x03, x02"; tls_proto="-tls1_1" ; add_proto_offered tls1_1 yes ;;
1697817048 TLSv1) tls_hexcode="x03, x01"; tls_proto="-tls1" ; add_proto_offered tls1 yes ;;
1697917049 SSLv3) tls_hexcode="x03, x00"; tls_proto="-ssl3" ; add_proto_offered ssl3 yes ;;
1698017050 esac
1698117051 fi
17052+ if ! sclient_supported "$tls_proto"; then
17053+ prln_local_problem "Cannot test for ticketbleed. $OPENSSL doesn't support \"s_client $tls_proto\"."
17054+ fileout "$jsonID" "WARN" "Cannot test for ticketbleed. $OPENSSL doesn't support \"s_client $tls_proto\"."
17055+ return 1
17056+ fi
1698217057 debugme echo "using protocol $tls_hexcode"
1698317058
16984- session_tckt_tls="$(sub_session_ticket_tls "$tls_proto")"
17059+ #FIXME: we likely have done this already before (either @ run_server_defaults() or at least the output
17060+ # from a previous handshake) --> would save 1x connect. We have TLS_TICKET but not yet the ticket itself #FIXME
17061+ #
17062+ $OPENSSL s_client $(s_client_options "$BUGS $tls_proto $PROXY $SNI -connect $NODEIP:$PORT") </dev/null >$TMPFILE 2>$ERRFILE
17063+ sclient_connect_successful $? "$TMPFILE"
17064+ if [[ $? -ne 0 ]]; then
17065+ prln_warning "$OPENSSL unable to connect to $NODEIP:$PORT when testing for ticketbleed."
17066+ fileout "$jsonID" "WARN" "$OPENSSL unable to connect to $NODEIP:$PORT when testing for ticketbleed."
17067+ return 1
17068+ fi
17069+ sessticket_tls="$(awk '/TLS session ticket:/,/^$/' "$TMPFILE" | awk '!/TLS session ticket/')"
17070+ sessticket_tls="$(sed -e 's/^.* - /x/g' -e 's/ .*$//g' <<< "$sessticket_tls" | tr '\n' ',')"
17071+ session_tckt_tls="$(sed -e 's/ /,x/g' -e 's/-/,x/g' <<< "$sessticket_tls")"
1698517072 if [[ "$session_tckt_tls" == "," ]]; then
1698617073 pr_svrty_best "not vulnerable (OK)"
1698717074 outln ", no session tickets"
@@ -20501,7 +20588,7 @@ find_openssl_binary() {
2050120588 for curve in "${curves_ossl[@]}"; do
2050220589 # Same as above, we just don't need a port for invalid.
2050320590 #FIXME: openssl 3 sometimes seems to hang when using '-connect invalid.' for up to 10 seconds
20504- $OPENSSL s_client -curves $curve -connect $NXCONNECT </dev/null 2>&1 | grep -Eiaq "Error with command|unknown option|cannot be set"
20591+ $OPENSSL s_client -curves $curve -connect $NXCONNECT </dev/null 2>&1 | grep -Eiaq "Error with command|unknown option|Call to SSL_CONF_cmd(.*) failed| cannot be set"
2050520592 [[ $? -ne 0 ]] && OSSL_SUPPORTED_CURVES+=" $curve "
2050620593 done
2050720594 fi
@@ -20820,7 +20907,7 @@ file output options (can also be preset via environment variables)
2082020907 --html additional output as HTML to file '\${NODE}-p\${port}\${YYYYMMDD-HHMM}.html'
2082120908 --htmlfile|-oH <htmlfile> additional output as HTML to the specified file or directory, similar to --logfile
2082220909 --out(f,F)ile|-oa/-oA <fname> log to a LOG,JSON,CSV,HTML file (see nmap). -oA/-oa: pretty/flat JSON.
20823- "auto" uses '\${NODE}-p\${port}\${YYYYMMDD-HHMM}'. If fname if a dir uses 'dir/\${NODE}-p\${port}\${YYYYMMDD-HHMM}'
20910+ "auto" uses '\${NODE}-p\${port}\${YYYYMMDD-HHMM}'. If fname is a dir uses 'dir/\${NODE}-p\${port}\${YYYYMMDD-HHMM}'
2082420911 --hints additional hints to findings
2082520912 --severity <severity> severities with lower level will be filtered for CSV+JSON, possible values <LOW|MEDIUM|HIGH|CRITICAL>
2082620913 --append if (non-empty) <logfile>, <csvfile>, <jsonfile> or <htmlfile> exists, append to file. Omits any header
@@ -23428,6 +23515,7 @@ set_rating_state() {
2342823515 return 1
2342923516 fi
2343023517
23518+ do_rating=true
2343123519 return 0
2343223520}
2343323521
@@ -23566,10 +23654,10 @@ set_skip_tests() {
2356623654# arg2: value (if no = provided)
2356723655parse_opt_equal_sign() {
2356823656 if [[ "$1" == *=* ]]; then
23569- echo ${1#*=}
23657+ safe_echo " ${1#*=}"
2357023658 return 1 # = means we don't need to shift args!
2357123659 else
23572- echo "$2 "
23660+ safe_echo "${2} "
2357323661 return 0 # we need to shift
2357423662 fi
2357523663}
@@ -24226,13 +24314,16 @@ parse_cmd_line() {
2422624314 [[ $CMDLINE_IP == one ]] && ( is_ipv4addr "$URI" || is_ipv6addr "$URI" ) && fatal_cmd_line "\"--ip=one\" plus supplying an IP address doesn't work" $ERR_CMDLINE
2422724315 "$do_mx_all_ips" && [[ "$NODNS" == none ]] && fatal_cmd_line "\"--mx\" and \"--nodns=none\" don't work together" $ERR_CMDLINE
2422824316
24229- if [[ -d $ADDTL_CA_FILES ]]; then
24317+ if [[ "${ADDTL_CA_FILES}" =~ \ ]]; then
24318+ fatal_cmd_line "The CA file \"${ADDTL_CA_FILES}\" must not contain spaces" $ERR_RESOURCE
24319+ fi
24320+ if [[ -d "${ADDTL_CA_FILES}" ]]; then
2423024321 ADDTL_CA_FILES="$ADDTL_CA_FILES/*.pem"
2423124322 else
2423224323 ADDTL_CA_FILES="${ADDTL_CA_FILES//,/ }"
2423324324 fi
24234- for fname in $ADDTL_CA_FILES; do
24235- [[ -s "$fname" ]] || fatal_cmd_line "CA file \"$fname\" does not exist" $ERR_RESOURCE
24325+ for fname in ${ ADDTL_CA_FILES} ; do
24326+ [[ -s "$fname" ]] || fatal_cmd_line "The CA file \"$fname\" does not exist" $ERR_RESOURCE
2423624327 grep -q 'BEGIN CERTIFICATE' "$fname" || fatal_cmd_line "\"$fname\" is not CA file in PEM format" $ERR_RESOURCE
2423724328 done
2423824329
0 commit comments