Redo PR for Opossum

Fixes #2833

This does a check for the opossum vulnerability, see https://opossum-attack.com/ .

It uses a separate function to send the payload and retrieve the result via `http_header_printf()`.  It doesn't use curl or wget. The latter wouldn't work anyway as according to the manpage as the HTTP header which needs to be sent must not contain LFs.  This function was introduced because `http_get_header()` -- which was renamed to `http_head()` -- could use wget if curl is not available. On the way to this PR `http_head()` was improved, so that timeouts were used for curl and wget for better maturity.

`http_header_printf()` now uses bach sockets , strips the URI so that a plaintext request is made. This will be done in the background because not every host will answer.

Done also:
- handling when PROXY is requested (try anyway directly as the payload is not "proxyable")
- print a message when no HTTP service is present
- try hard to use plaintext HTTP when auth is required for HTTPS and service HTTP would not be defined otherwise
- manpages
- help

Also when pwnedkeys are checked a not pwned certificate is labled not neutral but OK=green.
This commit is contained in:
Dirk Wetter
2025-07-12 20:59:50 +02:00
parent c467398a37
commit a4953d6e22
7 changed files with 166 additions and 41 deletions

View File

@ -5,6 +5,7 @@
* QUIC protocol check * QUIC protocol check
* bump SSLlabs rating guide to 2009r * bump SSLlabs rating guide to 2009r
* Check for Opossum vulnerability
### Features implemented / improvements in 3.2 ### Features implemented / improvements in 3.2

View File

@ -659,6 +659,9 @@ variable \f[CR]CCS_MAX_WAITSOCK\f[R].
\f[CR]\-T, \-\-ticketbleed\f[R] Checks for Ticketbleed memory leakage in \f[CR]\-T, \-\-ticketbleed\f[R] Checks for Ticketbleed memory leakage in
BigIP loadbalancers. BigIP loadbalancers.
.PP .PP
\f[CR]\-\-OP, \-\-opossum\f[R] Checks for HTTP to HTTPS upgrade
vulnerability named Opossum.
.PP
\f[CR]\-\-BB, \-\-robot\f[R] Checks for vulnerability to ROBOT / \f[CR]\-\-BB, \-\-robot\f[R] Checks for vulnerability to ROBOT /
(\f[I]Return Of Bleichenbacher\[cq]s Oracle Threat\f[R]) attack. (\f[I]Return Of Bleichenbacher\[cq]s Oracle Threat\f[R]) attack.
.PP .PP
@ -1312,6 +1315,8 @@ RFC 2246: The TLS Protocol Version 1.0
.IP \[bu] 2 .IP \[bu] 2
RFC 2595: Using TLS with IMAP, POP3 and ACAP RFC 2595: Using TLS with IMAP, POP3 and ACAP
.IP \[bu] 2 .IP \[bu] 2
RFC 2817: Upgrading to TLS Within HTTP/1.1
.IP \[bu] 2
RFC 2818: HTTP Over TLS RFC 2818: HTTP Over TLS
.IP \[bu] 2 .IP \[bu] 2
RFC 2830: Lightweight Directory Access Protocol (v3): Extension for RFC 2830: Lightweight Directory Access Protocol (v3): Extension for

View File

@ -590,6 +590,8 @@
<code>CCS_MAX_WAITSOCK</code>.</p> <code>CCS_MAX_WAITSOCK</code>.</p>
<p><code>-T, --ticketbleed</code> Checks for Ticketbleed memory <p><code>-T, --ticketbleed</code> Checks for Ticketbleed memory
leakage in BigIP loadbalancers.</p> leakage in BigIP loadbalancers.</p>
<p><code>--OP, --opossum</code> Checks for HTTP to HTTPS upgrade
vulnerability named Opossum.</p>
<p><code>--BB, --robot</code> Checks for vulnerability to ROBOT <p><code>--BB, --robot</code> Checks for vulnerability to ROBOT
/ (<em>Return Of Bleichenbachers Oracle Threat</em>) / (<em>Return Of Bleichenbachers Oracle Threat</em>)
attack.</p> attack.</p>
@ -1131,6 +1133,7 @@
<ul> <ul>
<li>RFC 2246: The TLS Protocol Version 1.0</li> <li>RFC 2246: The TLS Protocol Version 1.0</li>
<li>RFC 2595: Using TLS with IMAP, POP3 and ACAP</li> <li>RFC 2595: Using TLS with IMAP, POP3 and ACAP</li>
<li>RFC 2817: Upgrading to TLS Within HTTP/1.1</li>
<li>RFC 2818: HTTP Over TLS</li> <li>RFC 2818: HTTP Over TLS</li>
<li>RFC 2830: Lightweight Directory Access Protocol (v3): <li>RFC 2830: Lightweight Directory Access Protocol (v3):
Extension for Transport Layer Security</li> Extension for Transport Layer Security</li>

View File

@ -236,9 +236,11 @@ Also for multiple server certificates are being checked for as well as for the c
`-T, --ticketbleed` Checks for Ticketbleed memory leakage in BigIP loadbalancers. `-T, --ticketbleed` Checks for Ticketbleed memory leakage in BigIP loadbalancers.
`--BB, --robot` Checks for vulnerability to ROBOT / (*Return Of Bleichenbacher's Oracle Threat*) attack. `--OP, --opossum` Checks for HTTP to HTTPS upgrade vulnerability named Opossum.
`--SI, --starttls-injection` Checks for STARTTLS injection vulnerabilities (SMTP, IMAP, POP3 only). `socat` and OpenSSL >=1.1.0 is needed. `--BB, --robot` Checks for vulnerability to ROBOT / (*Return Of Bleichenbacher's Oracle Threat*) attack.
`--SI, --starttls-injection` Checks for STARTTLS injection vulnerabilities (SMTP, IMAP, POP3 only). `socat` and OpenSSL >=1.1.0 is needed.
`-R, --renegotiation` Tests renegotiation vulnerabilities. Currently there's a check for *Secure Renegotiation* and for *Secure Client-Initiated Renegotiation*. Please be aware that vulnerable servers to the latter can likely be DoSed very easily (HTTP). A check for *Insecure Client-Initiated Renegotiation* is not yet implemented. `-R, --renegotiation` Tests renegotiation vulnerabilities. Currently there's a check for *Secure Renegotiation* and for *Secure Client-Initiated Renegotiation*. Please be aware that vulnerable servers to the latter can likely be DoSed very easily (HTTP). A check for *Insecure Client-Initiated Renegotiation* is not yet implemented.
@ -490,6 +492,7 @@ Please note that for plain TLS-encrypted ports you must not specify the protocol
* RFC 2246: The TLS Protocol Version 1.0 * RFC 2246: The TLS Protocol Version 1.0
* RFC 2595: Using TLS with IMAP, POP3 and ACAP * RFC 2595: Using TLS with IMAP, POP3 and ACAP
* RFC 2817: Upgrading to TLS Within HTTP/1.1
* RFC 2818: HTTP Over TLS * RFC 2818: HTTP Over TLS
* RFC 2830: Lightweight Directory Access Protocol (v3): Extension for Transport Layer Security * RFC 2830: Lightweight Directory Access Protocol (v3): Extension for Transport Layer Security
* RFC 3207: SMTP Service Extension for Secure SMTP over Transport Layer Security * RFC 3207: SMTP Service Extension for Secure SMTP over Transport Layer Security
@ -551,7 +554,6 @@ Please note that for plain TLS-encrypted ports you must not specify the protocol
**etc/client-simulation.txt** contains client simulation data. **etc/client-simulation.txt** contains client simulation data.
**etc/cipher-mapping.txt** provides a mandatory file with mapping from OpenSSL cipher suites names to the ones from IANA / used in the RFCs. **etc/cipher-mapping.txt** provides a mandatory file with mapping from OpenSSL cipher suites names to the ones from IANA / used in the RFCs.
**etc/tls_data.txt** provides a mandatory file for ciphers (bash sockets) and key material. **etc/tls_data.txt** provides a mandatory file for ciphers (bash sockets) and key material.

View File

@ -48,7 +48,7 @@ $edited_html =~ s/&apos;/'/g;
$diff = diff \$edited_html, \$out; $diff = diff \$edited_html, \$out;
cmp_ok($edited_html, "eq", $out, "Checking if HTML file matches terminal output") or ok($edited_html eq $out, "Checking if HTML file matches terminal output") or
diag ("\n%s\n", "$diff"); diag ("\n%s\n", "$diff");
$tests++; $tests++;
@ -82,7 +82,7 @@ $debughtml =~ s/.*Using bash .*\n//g;
$diff = diff \$debughtml, \$html; $diff = diff \$debughtml, \$html;
cmp_ok($debughtml, "eq", $html, "Checking if HTML file created with --debug 4 matches HTML file created without --debug") or ok($debughtml eq $html, "Checking if HTML file created with --debug 4 matches HTML file created without --debug") or
diag ("\n%s\n", "$diff"); diag ("\n%s\n", "$diff");
$tests++; $tests++;

View File

@ -90,6 +90,7 @@
"heartbleed","testssl.sh/81.169.166.184","443","OK","not vulnerable, no heartbeat extension","CVE-2014-0160","CWE-119" "heartbleed","testssl.sh/81.169.166.184","443","OK","not vulnerable, no heartbeat extension","CVE-2014-0160","CWE-119"
"CCS","testssl.sh/81.169.166.184","443","OK","not vulnerable","CVE-2014-0224","CWE-310" "CCS","testssl.sh/81.169.166.184","443","OK","not vulnerable","CVE-2014-0224","CWE-310"
"ticketbleed","testssl.sh/81.169.166.184","443","OK","no session ticket extension","CVE-2016-9244","CWE-200" "ticketbleed","testssl.sh/81.169.166.184","443","OK","no session ticket extension","CVE-2016-9244","CWE-200"
"opossum","testssl.sh/81.169.166.184","443","OK","not vulnerable","CVE-2025-49812","CWE-287"
"ROBOT","testssl.sh/81.169.166.184","443","OK","not vulnerable","CVE-2017-17382 CVE-2017-17427 CVE-2017-17428 CVE-2017-13098 CVE-2017-1000385 CVE-2017-13099 CVE-2016-6883 CVE-2012-5081 CVE-2017-6168","CWE-203" "ROBOT","testssl.sh/81.169.166.184","443","OK","not vulnerable","CVE-2017-17382 CVE-2017-17427 CVE-2017-17428 CVE-2017-13098 CVE-2017-1000385 CVE-2017-13099 CVE-2016-6883 CVE-2012-5081 CVE-2017-6168","CWE-203"
"secure_renego","testssl.sh/81.169.166.184","443","OK","supported","","CWE-310" "secure_renego","testssl.sh/81.169.166.184","443","OK","supported","","CWE-310"
"secure_client_renego","testssl.sh/81.169.166.184","443","OK","not vulnerable","CVE-2011-1473","CWE-310" "secure_client_renego","testssl.sh/81.169.166.184","443","OK","not vulnerable","CVE-2011-1473","CWE-310"

View File

@ -1786,12 +1786,13 @@ filter_input() {
sed -e 's/#.*$//' -e '/^$/d' <<< "$1" | tr -d '\n' | tr -d '\t' | tr -d '\r' sed -e 's/#.*$//' -e '/^$/d' <<< "$1" | tr -d '\n' | tr -d '\t' | tr -d '\r'
} }
# Dl's any URL (arg1) via HTTP 1.1 GET from port 80, arg2: file to store http body. # Dl any URL (arg1) via HTTP 1.1 GET from port 80 or 443 (curl/wget). arg2: file to store http body.
# Proxy is not honored yet (see cmd line switches) -- except when using curl or wget. # Proxy is not honored yet (see cmd line switches) -- except when using curl or wget.
# There the environment variable is used automatically # The PROXY environment variable is used when specified
# Currently it is being used by check_revocation_crl() only. # Currently this is being used by check_revocation_crl() only.
#
http_get() { http_get() {
local proto z local proto="" foo=""
local node="" query="" local node="" query=""
local dl="$2" local dl="$2"
local useragent="$UA_STD" local useragent="$UA_STD"
@ -1825,7 +1826,7 @@ http_get() {
# Worst option: slower and hiccups with chunked transfers. Workaround for the # Worst option: slower and hiccups with chunked transfers. Workaround for the
# latter is using HTTP/1.0. We do not support https here, yet. # latter is using HTTP/1.0. We do not support https here, yet.
# First the URL will be split # First the URL will be split
IFS=/ read -r proto z node query <<< "$1" IFS=/ read -r proto foo node query <<< "$1"
proto=${proto%:} proto=${proto%:}
if [[ "$proto" != http ]]; then if [[ "$proto" != http ]]; then
pr_warning "protocol $proto not supported yet" pr_warning "protocol $proto not supported yet"
@ -1844,7 +1845,7 @@ http_get() {
printf -- "%b" "GET $proto://$node/$query HTTP/1.0\r\nUser-Agent: $useragent\r\nHost: $node\r\nAccept: */*\r\n\r\n" >&33 printf -- "%b" "GET $proto://$node/$query HTTP/1.0\r\nUser-Agent: $useragent\r\nHost: $node\r\nAccept: */*\r\n\r\n" >&33
fi fi
else else
IFS=/ read -r proto z node query <<< "$1" IFS=/ read -r proto foo node query <<< "$1"
exec 33<>/dev/tcp/$node/80 exec 33<>/dev/tcp/$node/80
printf -- "%b" "GET /$query HTTP/1.0\r\nUser-Agent: $useragent\r\nHost: $node\r\nAccept: */*\r\n\r\n" >&33 printf -- "%b" "GET /$query HTTP/1.0\r\nUser-Agent: $useragent\r\nHost: $node\r\nAccept: */*\r\n\r\n" >&33
fi fi
@ -1861,55 +1862,105 @@ http_get() {
fi fi
} }
# Outputs the headers when downloading any URL (arg1) via HTTP 1.1 GET from port 80. # Outputs the HTTP headers via HTTP 1.1 HEAD command via HTTPS and a valid certificate
# arg1 is the URL
# arg2 is optional and could be a request header. curl/wget don't send empty headers otherwise
#
# Only works if curl or wget is available. # Only works if curl or wget is available.
# There the environment variable is used automatically # The proxy environment variable is used automatically.
# Currently it is being used by check_pwnedkeys() only. # Currently it is being used by check_pwnedkeys() only
http_get_header() { #
http_head() {
local proto local proto
local node="" query="" local node="" query=""
local dl="$2" local request_header="$2"
local useragent="$UA_STD" local useragent="$UA_STD"
local jsonID="http_get_header" local response_headers=""
local headers local xtra_params=""
local -i ret local -i ret
"$SNEAKY" && useragent="$UA_SNEAKY" "$SNEAKY" && useragent="$UA_SNEAKY"
if type -p curl &>/dev/null; then if type -p curl &>/dev/null; then
xtra_params="--connect-timeout $HEADER_MAXSLEEP --head -s"
if [[ -z "$PROXY" ]]; then if [[ -z "$PROXY" ]]; then
headers="$(curl --head -s --noproxy '*' -A $''"$useragent"'' "$1")" response_headers="$(curl $xtra_params --noproxy '*' -H $''"$request_header"'' -A $''"$useragent"'' "$1")"
else else
# for the sake of simplicity assume the proxy is using http # for the sake of simplicity assume the proxy is using http
headers="$(curl --head -s -x $PROXYIP:$PROXYPORT -A $''"$useragent"'' "$1")" response_headers="$(curl $xtra_params -x $PROXYIP:$PROXYPORT -H $''"$request_header"'' -A $''"$useragent"'' "$1")"
fi fi
ret=$? ret=$?
[[ $ret -eq 0 ]] && tm_out "$headers" [[ $ret -eq 0 ]] && tm_out "$response_headers"
return $ret return $ret
elif type -p wget &>/dev/null; then elif type -p wget &>/dev/null; then
xtra_params="--timeout=$HEADER_MAXSLEEP --tries=1 --cache=off"
# wget has no proxy command line. We need to use http_proxy instead. And for the sake of simplicity # wget has no proxy command line. We need to use http_proxy instead. And for the sake of simplicity
# assume the GET protocol we query is using http -- http_proxy is the $ENV not for the connection TO # assume the GET protocol we query is using http -- http_proxy is the $ENV not for the connection TO
# the proxy, but for the protocol we query THROUGH the proxy # the proxy, but for the protocol we query THROUGH the proxy
if [[ -z "$PROXY" ]]; then if [[ -z "$PROXY" ]]; then
headers="$(wget --no-proxy -q -S -U $''"$useragent"'' -O /dev/null "$1" 2>&1)" response_headers="$(wget --no-proxy -q -S $xtra_params --header $''"$request_header"'' -U $''"$useragent"'' -O /dev/null "$1" 2>&1)"
else else
if [[ -z "$http_proxy" ]]; then if [[ -z "$http_proxy" ]]; then
headers="$(http_proxy=http://$PROXYIP:$PROXYPORT wget -q -S -U $''"$useragent"'' -O /dev/null "$1" 2>&1)" response_headers="$(http_proxy=http://$PROXYIP:$PROXYPORT wget -q -S $xtra_params --header $''"$request_header"'' -U $''"$useragent"'' -O /dev/null "$1" 2>&1)"
else else
headers="$(wget -q -S -U $''"$useragent"'' -O /dev/null "$1" 2>&1)" response_headers="$(wget -q -S $xtra_params --header $''"$request_header"'' -U $''"$useragent"'' -O /dev/null "$1" 2>&1)"
fi fi
fi fi
ret=$? ret=$?
[[ $ret -eq 0 ]] && tm_out "$headers" [[ $ret -eq 0 ]] && tm_out "$response_headers"
# wget(1): "8: Server issued an error response.". Happens e.g. when 404 is returned. However also if the call wasn't correct (400) # wget(1): "8: Server issued an error response.". Happens e.g. when 404 is returned. However also if the call wasn't correct (400)
# So we assume for now that everything is submitted correctly. We parse the error code too later # So we assume for now that everything is submitted correctly. We parse the error code too later
[[ $ret -eq 8 ]] && ret=0 && tm_out "$headers" [[ $ret -eq 8 ]] && ret=0 && tm_out "$response_headers"
return $ret return $ret
else else
return 1 return 1
fi fi
} }
# does a simple http head via printf with no proxy, only used by run_opossum()
# arg1: URL
# arg2: extra http header
#
# return codes:
# 0: all fine
# 1: server dind't respond within HEADER_MAXSLEEP
# 3: server dind't respond within HEADER_MAXSLEEP and PROXY was defined
#
http_header_printf() {
local request_header="$2"
local useragent="$UA_STD"
local tmpfile=$TEMPDIR/$NODE.$NODEIP.http_header_printf.log
local errfile=$TEMPDIR/$NODE.$NODEIP.http_header_printf-err.log
local -i ret=0
local proto="" foo="" node="" query=""
[[ $DEBUG -eq 0 ]] && errfile=/dev/null
IFS=/ read -r proto foo node query <<< "$1"
exec 33<>/dev/tcp/$node/80
printf -- "%b" "HEAD ${proto}//${node}/${query} HTTP/1.1\r\nUser-Agent: ${useragent}\r\nHost: ${node}\r\n${request_header}\r\nAccept: */*\r\n\r\n\r\n" >&33 2>$errfile &
wait_kill $! $HEADER_MAXSLEEP
if [[ $? -ne 0 ]]; then
# not killed
if [[ -n "$PROXY" ]]; then
ret=3
fi
ret=1
else
ret=0
fi
if [[ $DEBUG -eq 0 ]] ; then
cat <&33
else
cat <&33 >$tmpfile
cat $tmpfile
fi
exec 33<&-
exec 33>&-
return $ret
}
ldap_get() { ldap_get() {
local ldif local ldif
local -i success local -i success
@ -1940,6 +1991,7 @@ ldap_get() {
# 1 - key not found in database # 1 - key not found in database
# 2 - key found in database # 2 - key found in database
# 7 - network/proxy failure # 7 - network/proxy failure
#
check_pwnedkeys() { check_pwnedkeys() {
local cert="$1" local cert="$1"
local cert_key_algo="$2" local cert_key_algo="$2"
@ -1969,7 +2021,7 @@ check_pwnedkeys() {
fi fi
fingerprint="$($OPENSSL pkey -pubin -outform DER <<< "$pubkey" 2>/dev/null | $OPENSSL dgst -sha256 -hex 2>/dev/null)" fingerprint="$($OPENSSL pkey -pubin -outform DER <<< "$pubkey" 2>/dev/null | $OPENSSL dgst -sha256 -hex 2>/dev/null)"
fingerprint="${fingerprint#*= }" fingerprint="${fingerprint#*= }"
response="$(http_get_header "https://v1.pwnedkeys.com/$fingerprint")" response="$(http_head "https://v1.pwnedkeys.com/$fingerprint")"
# Handle curl's/wget's connectivity exit codes # Handle curl's/wget's connectivity exit codes
case $? in case $? in
4|5|7) return 7 ;; 4|5|7) return 7 ;;
@ -9927,7 +9979,7 @@ certificate_info() {
check_pwnedkeys "$HOSTCERT" "$cert_key_algo" "$cert_keysize" check_pwnedkeys "$HOSTCERT" "$cert_key_algo" "$cert_keysize"
case "$?" in case "$?" in
0) outln "not checked"; fileout "pwnedkeys${json_postfix}" "INFO" "not checked" ;; 0) outln "not checked"; fileout "pwnedkeys${json_postfix}" "INFO" "not checked" ;;
1) outln "not in database"; fileout "pwnedkeys${json_postfix}" "INFO" "not in database" ;; 1) pr_svrty_good "not in database"; fileout "pwnedkeys${json_postfix}" "OK" "not in database" ;;
2) pr_svrty_critical "NOT ok --"; outln " key appears in database"; fileout "pwnedkeys${json_postfix}" "CRITICAL" "private key is known" ;; 2) pr_svrty_critical "NOT ok --"; outln " key appears in database"; fileout "pwnedkeys${json_postfix}" "CRITICAL" "private key is known" ;;
7) prln_warning "error querying https://v1.pwnedkeys.com"; fileout "pwnedkeys${json_postfix}" "WARN" "connection error" ;; 7) prln_warning "error querying https://v1.pwnedkeys.com"; fileout "pwnedkeys${json_postfix}" "WARN" "connection error" ;;
esac esac
@ -12212,6 +12264,7 @@ code2network() {
# sockets inspired by https://blog.chris007.de/using-bash-for-network-socket-operation/ # sockets inspired by https://blog.chris007.de/using-bash-for-network-socket-operation/
# ARG1: hexbytes separated by commas, with a leading comma # ARG1: hexbytes separated by commas, with a leading comma
# ARG2: seconds to sleep # ARG2: seconds to sleep
#
socksend_clienthello() { socksend_clienthello() {
local data="" local data=""
@ -12230,6 +12283,7 @@ socksend_clienthello() {
# ARG1: hexbytes -- preceded by x -- separated by commas, with a leading comma # ARG1: hexbytes -- preceded by x -- separated by commas, with a leading comma
# ARG2: seconds to sleep # ARG2: seconds to sleep
#
socksend() { socksend() {
local data line local data line
@ -17339,6 +17393,7 @@ run_ccs_injection(){
# see https://blog.filippo.io/finding-ticketbleed/ | https://filippo.io/ticketbleed/ # see https://blog.filippo.io/finding-ticketbleed/ | https://filippo.io/ticketbleed/
#
run_ticketbleed() { run_ticketbleed() {
local tls_hexcode tls_proto="" local tls_hexcode tls_proto=""
local sessticket_tls="" session_tckt_tls="" local sessticket_tls="" session_tckt_tls=""
@ -17363,7 +17418,7 @@ run_ticketbleed() {
pr_bold " Ticketbleed"; out " ($cve), experiment. " pr_bold " Ticketbleed"; out " ($cve), experiment. "
if [[ "$SERVICE" != HTTP ]] && [[ "$CLIENT_AUTH" != required ]]; then if [[ "$SERVICE" != HTTP ]] && [[ "$CLIENT_AUTH" != required ]]; then
outln "(applicable only for HTTPS)" outln "(applicable only for HTTP service)"
fileout "$jsonID" "INFO" "not applicable, not HTTP" "$cve" "$cwe" fileout "$jsonID" "INFO" "not applicable, not HTTP" "$cve" "$cwe"
return 0 return 0
fi fi
@ -17625,6 +17680,55 @@ run_ticketbleed() {
return $ret return $ret
} }
# https://opossum-attack.com/, TLS Upgrade via old RFC 2817
#
run_opossum() {
local cve='CVE-2025-49812'
local jsonID="opossum"
local cwe="CWE-287"
local -i ret=0
local uri=$URI
local service="$SERVICE"
local response=""
[[ -n "$STARTTLS" ]] && return 0
[[ $VULN_COUNT -le $VULN_THRESHLD ]] && outln && pr_headlineln " Testing for Opossum vulnerability " && outln
pr_bold " Opossum"; out " ($cve) "
# we're trying to connect also if ASSUME_HTTP is not set, there should be either one of following hints though
if [[ -z $service ]]; then
[[ $uri =~ ^http ]] && service=HTTP # https provided as target/URL
[[ "$CLIENT_AUTH" == required ]] && service=HTTP # also try when client auth is requested (we dont use it over cleartext)
fi
case $service in
HTTP)
uri=${URI/https:\/\//}
response=$(http_header_printf http://${uri} 'Upgrade: TLS/1.0\r\n\r\nClose\r\n')
# In any case we use $response but we handle the return codes
case $? in
0) ret=0 ;;
1|3) ret=7 ;; # got stuck
esac
if [[ $response =~ Upgrade:\ TLS ]]; then
prln_svrty_high "VULNERABLE (NOT ok)"
fileout "$jsonID" "CRITICAL" "VULNERABLE" "$cve" "$cwe" "$hint"
else
prln_svrty_good "not vulnerable (OK)"
fileout "$jsonID" "OK" "not vulnerable $append" "$cve" "$cwe"
fi
;;
IMAP|FTP|POP3|SMTP|LMTP|NNTP)
outln "(implemented currently for HTTP only)"
fileout "$jsonID" "INFO" "not yet implemented" "$cve" "$cwe"
;;
*) outln "(applicable only for HTTP service)"
fileout "$jsonID" "INFO" "not applicable, not HTTP" "$cve" "$cwe"
;;
esac
return $ret
}
# Overview @ http://www.exploresecurity.com/wp-content/uploads/custom/SSL_manual_cheatsheet.html # Overview @ http://www.exploresecurity.com/wp-content/uploads/custom/SSL_manual_cheatsheet.html
# #
run_renego() { run_renego() {
@ -21257,6 +21361,7 @@ single check as <options> ("$PROG_NAME URI" does everything except -E and -g):
-H, --heartbleed tests for Heartbleed vulnerability -H, --heartbleed tests for Heartbleed vulnerability
-I, --ccs, --ccs-injection tests for CCS injection vulnerability -I, --ccs, --ccs-injection tests for CCS injection vulnerability
-T, --ticketbleed tests for Ticketbleed vulnerability in BigIP loadbalancers -T, --ticketbleed tests for Ticketbleed vulnerability in BigIP loadbalancers
--OP, --opossum tests for Opossum vulnerability
--BB, --robot tests for Return of Bleichenbacher's Oracle Threat (ROBOT) vulnerability --BB, --robot tests for Return of Bleichenbacher's Oracle Threat (ROBOT) vulnerability
--SI, --starttls-injection tests for STARTTLS injection issues --SI, --starttls-injection tests for STARTTLS injection issues
-R, --renegotiation tests for renegotiation vulnerabilities -R, --renegotiation tests for renegotiation vulnerabilities
@ -23980,6 +24085,7 @@ initialize_globals() {
do_breach=false do_breach=false
do_ccs_injection=false do_ccs_injection=false
do_ticketbleed=false do_ticketbleed=false
do_opossum=false
do_robot=false do_robot=false
do_cipher_per_proto=false do_cipher_per_proto=false
do_crime=false do_crime=false
@ -24028,6 +24134,7 @@ set_scanning_defaults() {
do_heartbleed="$OFFENSIVE" do_heartbleed="$OFFENSIVE"
do_ccs_injection="$OFFENSIVE" do_ccs_injection="$OFFENSIVE"
do_ticketbleed="$OFFENSIVE" do_ticketbleed="$OFFENSIVE"
do_opossum=true
do_robot="$OFFENSIVE" do_robot="$OFFENSIVE"
do_crime=true do_crime=true
do_freak=true do_freak=true
@ -24048,9 +24155,9 @@ set_scanning_defaults() {
do_tls_fallback_scsv=true do_tls_fallback_scsv=true
do_client_simulation=true do_client_simulation=true
if "$OFFENSIVE"; then if "$OFFENSIVE"; then
VULN_COUNT=17 VULN_COUNT=18
else else
VULN_COUNT=13 VULN_COUNT=14
fi fi
do_rating=true do_rating=true
} }
@ -24061,10 +24168,10 @@ count_do_variables() {
local -i true_nr=0 local -i true_nr=0
for gbl in do_allciphers do_vulnerabilities do_beast do_lucky13 do_breach do_ccs_injection do_ticketbleed do_cipher_per_proto do_crime \ for gbl in do_allciphers do_vulnerabilities do_beast do_lucky13 do_breach do_ccs_injection do_ticketbleed do_cipher_per_proto do_crime \
do_freak do_logjam do_drown do_header do_heartbleed do_mx_all_ips do_fs do_protocols do_rc4 do_starttls_injection do_grease do_robot do_renego \ do_freak do_logjam do_drown do_header do_heartbleed do_mx_all_ips do_fs do_protocols do_rc4 do_starttls_injection do_grease \
do_cipherlists do_server_defaults do_server_preference do_ssl_poodle do_tls_fallback_scsv do_winshock \ do_opossum do_robot do_renego do_cipherlists do_server_defaults do_server_preference do_ssl_poodle do_tls_fallback_scsv \
do_sweet32 do_client_simulation do_cipher_match do_tls_sockets do_mass_testing do_display_only do_rating; do do_winshock do_sweet32 do_client_simulation do_cipher_match do_tls_sockets do_mass_testing do_display_only do_rating; do
"${!gbl}" && ((true_nr++)) "${!gbl}" && ((true_nr++))
done done
return $true_nr return $true_nr
} }
@ -24074,10 +24181,10 @@ debug_globals() {
local gbl local gbl
for gbl in do_allciphers do_vulnerabilities do_beast do_lucky13 do_breach do_ccs_injection do_ticketbleed do_cipher_per_proto do_crime \ for gbl in do_allciphers do_vulnerabilities do_beast do_lucky13 do_breach do_ccs_injection do_ticketbleed do_cipher_per_proto do_crime \
do_freak do_logjam do_drown do_header do_heartbleed do_mx_all_ips do_fs do_protocols do_rc4 do_starttls_injection do_grease do_robot do_renego \ do_freak do_logjam do_drown do_header do_heartbleed do_mx_all_ips do_fs do_protocols do_rc4 do_starttls_injection do_grease\
do_cipherlists do_server_defaults do_server_preference do_ssl_poodle do_tls_fallback_scsv do_winshock \ do_opossum do_robot do_renego do_cipherlists do_server_defaults do_server_preference do_ssl_poodle do_tls_fallback_scsv \
do_sweet32 do_client_simulation do_cipher_match do_tls_sockets do_mass_testing do_display_only do_rating; do do_winshock do_sweet32 do_client_simulation do_cipher_match do_tls_sockets do_mass_testing do_display_only do_rating; do
printf "%-22s = %s\n" $gbl "${!gbl}" printf "%-22s = %s\n" $gbl "${!gbl}"
done done
# ${!var} is an indirect expansion, see https://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html # ${!var} is an indirect expansion, see https://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html
# Example: https://stackoverflow.com/questions/8515411/what-is-indirect-expansion-what-does-var-mean#8515492 # Example: https://stackoverflow.com/questions/8515411/what-is-indirect-expansion-what-does-var-mean#8515492
@ -24283,6 +24390,7 @@ parse_cmd_line() {
do_heartbleed="$OFFENSIVE" do_heartbleed="$OFFENSIVE"
do_ccs_injection="$OFFENSIVE" do_ccs_injection="$OFFENSIVE"
do_ticketbleed="$OFFENSIVE" do_ticketbleed="$OFFENSIVE"
do_opossum=true
do_robot="$OFFENSIVE" do_robot="$OFFENSIVE"
do_renego=true do_renego=true
do_crime=true do_crime=true
@ -24299,9 +24407,9 @@ parse_cmd_line() {
do_rc4=true do_rc4=true
do_starttls_injection=true do_starttls_injection=true
if "$OFFENSIVE"; then if "$OFFENSIVE"; then
VULN_COUNT=17 VULN_COUNT=18
else else
VULN_COUNT=13 VULN_COUNT=14
fi fi
;; ;;
--ids-friendly) --ids-friendly)
@ -24319,6 +24427,10 @@ parse_cmd_line() {
do_ticketbleed=true do_ticketbleed=true
((VULN_COUNT++)) ((VULN_COUNT++))
;; ;;
--OP|--opossum)
do_opossum=true
((VULN_COUNT++))
;;
-BB|--BB|--robot) -BB|--BB|--robot)
do_robot=true do_robot=true
;; ;;
@ -24984,6 +25096,7 @@ lets_roll() {
"$do_heartbleed" && { run_heartbleed; ret=$(($? + ret)); stopwatch run_heartbleed; } "$do_heartbleed" && { run_heartbleed; ret=$(($? + ret)); stopwatch run_heartbleed; }
"$do_ccs_injection" && { run_ccs_injection; ret=$(($? + ret)); stopwatch run_ccs_injection; } "$do_ccs_injection" && { run_ccs_injection; ret=$(($? + ret)); stopwatch run_ccs_injection; }
"$do_ticketbleed" && { run_ticketbleed; ret=$(($? + ret)); stopwatch run_ticketbleed; } "$do_ticketbleed" && { run_ticketbleed; ret=$(($? + ret)); stopwatch run_ticketbleed; }
"$do_opossum" && { run_opossum; ret=$(($? + ret)); stopwatch run_opossum; }
"$do_robot" && { run_robot; ret=$(($? + ret)); stopwatch run_robot; } "$do_robot" && { run_robot; ret=$(($? + ret)); stopwatch run_robot; }
"$do_renego" && { run_renego; ret=$(($? + ret)); stopwatch run_renego; } "$do_renego" && { run_renego; ret=$(($? + ret)); stopwatch run_renego; }
"$do_crime" && { run_crime; ret=$(($? + ret)); stopwatch run_crime; } "$do_crime" && { run_crime; ret=$(($? + ret)); stopwatch run_crime; }