Skip to content

Commit dba3bd0

Browse files
committed
Opossum vulnerabilty
Fixes #2833 This does a check for the opossum vulnerability, see https://opossum-attack.com/. Currently it uses wget or curl, so one if them has to be present. Proxy handling was introduced in check_pwnedkeys() which should help that function too. Also timeouts were used for curl and wget for better maturity. Todos: - handling when neither curl or wget is present - at least a warning when no HTTP service is present - take care of the diffs in http_get_header() to make this work --> make sure it still does using check_pwnedkeys() - -H ''? - ret codes - backport proxy stuff in http_get_header() to 3.2 - backport curl/wget timeouts to 3.2 - manpage (incl. RFC 2817)
1 parent c467398 commit dba3bd0

2 files changed

Lines changed: 75 additions & 24 deletions

File tree

t/baseline_data/default_testssl.csvfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@
9090
"heartbleed","testssl.sh/81.169.166.184","443","OK","not vulnerable, no heartbeat extension","CVE-2014-0160","CWE-119"
9191
"CCS","testssl.sh/81.169.166.184","443","OK","not vulnerable","CVE-2014-0224","CWE-310"
9292
"ticketbleed","testssl.sh/81.169.166.184","443","OK","no session ticket extension","CVE-2016-9244","CWE-200"
93+
"opossum","testssl.sh/81.169.166.184","443","OK","not vulnerable","CVE-2025-49812","CWE-74"
9394
"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"
9495
"secure_renego","testssl.sh/81.169.166.184","443","OK","supported","","CWE-310"
9596
"secure_client_renego","testssl.sh/81.169.166.184","443","OK","not vulnerable","CVE-2011-1473","CWE-310"

testssl.sh

Lines changed: 74 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1790,6 +1790,7 @@ filter_input() {
17901790
# Proxy is not honored yet (see cmd line switches) -- except when using curl or wget.
17911791
# There the environment variable is used automatically
17921792
# Currently it is being used by check_revocation_crl() only.
1793+
#
17931794
http_get() {
17941795
local proto z
17951796
local node="" query=""
@@ -1864,52 +1865,56 @@ http_get() {
18641865
# Outputs the headers when downloading any URL (arg1) via HTTP 1.1 GET from port 80.
18651866
# Only works if curl or wget is available.
18661867
# There the environment variable is used automatically
1867-
# Currently it is being used by check_pwnedkeys() only.
1868+
# Currently it is being used by check_pwnedkeys() and run_opossum()
1869+
#
18681870
http_get_header() {
18691871
local proto
18701872
local node="" query=""
1871-
local dl="$2"
1873+
local request_header="$2"
18721874
local useragent="$UA_STD"
18731875
local jsonID="http_get_header"
1874-
local headers
1876+
local response_headers
18751877
local -i ret
18761878

18771879
"$SNEAKY" && useragent="$UA_SNEAKY"
18781880

18791881
if type -p curl &>/dev/null; then
1882+
timeout="--connect-timeout $HEADER_MAXSLEEP"
18801883
if [[ -z "$PROXY" ]]; then
1881-
headers="$(curl --head -s --noproxy '*' -A $''"$useragent"'' "$1")"
1884+
response_headers="$(curl --head -s $timeout --noproxy '*' -H $''"$request_header"'' -A $''"$useragent"'' "$1")"
18821885
else
18831886
# for the sake of simplicity assume the proxy is using http
1884-
headers="$(curl --head -s -x $PROXYIP:$PROXYPORT -A $''"$useragent"'' "$1")"
1887+
response_headers="$(curl --head -s $timeout -x $PROXYIP:$PROXYPORT -H $''"$request_header"'' -A $''"$useragent"'' "$1")"
18851888
fi
18861889
ret=$?
1887-
[[ $ret -eq 0 ]] && tm_out "$headers"
1890+
tm_out "$response_headers"
18881891
return $ret
18891892
elif type -p wget &>/dev/null; then
1893+
timeout="--timeout=$HEADER_MAXSLEEP --tries=0"
18901894
# wget has no proxy command line. We need to use http_proxy instead. And for the sake of simplicity
18911895
# assume the GET protocol we query is using http -- http_proxy is the $ENV not for the connection TO
18921896
# the proxy, but for the protocol we query THROUGH the proxy
18931897
if [[ -z "$PROXY" ]]; then
1894-
headers="$(wget --no-proxy -q -S -U $''"$useragent"'' -O /dev/null "$1" 2>&1)"
1898+
response_headers="$(wget --no-proxy -q -S $timeout --header $''"$request_header"'' -U $''"$useragent"'' -O /dev/null "$1" 2>&1)"
18951899
else
18961900
if [[ -z "$http_proxy" ]]; then
1897-
headers="$(http_proxy=http://$PROXYIP:$PROXYPORT wget -q -S -U $''"$useragent"'' -O /dev/null "$1" 2>&1)"
1901+
response_headers="$(http_proxy=http://$PROXYIP:$PROXYPORT wget -q -S $timeout --header $''"$request_header"'' -U $''"$useragent"'' -O /dev/null "$1" 2>&1)"
18981902
else
1899-
headers="$(wget -q -S -U $''"$useragent"'' -O /dev/null "$1" 2>&1)"
1903+
response_headers="$(wget -q -S $timeout --header $''"$request_header"'' -U $''"$useragent"'' -O /dev/null "$1" 2>&1)"
19001904
fi
19011905
fi
19021906
ret=$?
1903-
[[ $ret -eq 0 ]] && tm_out "$headers"
1907+
tm_out "$response_headers"
19041908
# wget(1): "8: Server issued an error response.". Happens e.g. when 404 is returned. However also if the call wasn't correct (400)
19051909
# So we assume for now that everything is submitted correctly. We parse the error code too later
1906-
[[ $ret -eq 8 ]] && ret=0 && tm_out "$headers"
1910+
[[ $ret -eq 8 ]] && ret=0 && tm_out "$response_headers"
19071911
return $ret
19081912
else
19091913
return 1
19101914
fi
19111915
}
19121916

1917+
19131918
ldap_get() {
19141919
local ldif
19151920
local -i success
@@ -1940,6 +1945,7 @@ ldap_get() {
19401945
# 1 - key not found in database
19411946
# 2 - key found in database
19421947
# 7 - network/proxy failure
1948+
#
19431949
check_pwnedkeys() {
19441950
local cert="$1"
19451951
local cert_key_algo="$2"
@@ -17625,6 +17631,41 @@ run_ticketbleed() {
1762517631
return $ret
1762617632
}
1762717633

17634+
# https://opossum-attack.com/, TLS Upgrade via old RFC 2817
17635+
#
17636+
run_opossum() {
17637+
local cve='CVE-2025-49812'
17638+
local jsonID="opossum"
17639+
local cwe="CWE-74"
17640+
local -i ret=0
17641+
17642+
[[ -n "$STARTTLS" ]] && return 0
17643+
[[ $VULN_COUNT -le $VULN_THRESHLD ]] && outln && pr_headlineln " Testing for Opossum vulnerability " && outln
17644+
pr_bold " Opossum"; out " ($cve) "
17645+
17646+
case $SERVICE in
17647+
HTTP)
17648+
response=$(http_get_header $NODE 'Upgrade: TLS/1.0\r\n\r\nClose\r\n')
17649+
case $? in
17650+
0) ret=0 ;;
17651+
*) ret=7 ;;
17652+
esac
17653+
if [[ $response =~ Upgrade:\ TLS ]]; then
17654+
pr_svrty_critical "VULNERABLE (NOT ok)"
17655+
fileout "$jsonID" "CRITICAL" "VULNERABLE" "$cve" "$cwe" "$hint"
17656+
else
17657+
pr_svrty_best "not vulnerable (OK)"; out "$append"
17658+
fileout "$jsonID" "OK" "not vulnerable $append" "$cve" "$cwe"
17659+
fi
17660+
echo
17661+
;;
17662+
*) [[ $DEBUG -ge 1 ]] && echo "not implemented yet"
17663+
;;
17664+
esac
17665+
return 0
17666+
}
17667+
17668+
1762817669
# Overview @ http://www.exploresecurity.com/wp-content/uploads/custom/SSL_manual_cheatsheet.html
1762917670
#
1763017671
run_renego() {
@@ -21257,6 +21298,7 @@ single check as <options> ("$PROG_NAME URI" does everything except -E and -g):
2125721298
-H, --heartbleed tests for Heartbleed vulnerability
2125821299
-I, --ccs, --ccs-injection tests for CCS injection vulnerability
2125921300
-T, --ticketbleed tests for Ticketbleed vulnerability in BigIP loadbalancers
21301+
--OP, --opossum tests for Opossum vulnerability
2126021302
--BB, --robot tests for Return of Bleichenbacher's Oracle Threat (ROBOT) vulnerability
2126121303
--SI, --starttls-injection tests for STARTTLS injection issues
2126221304
-R, --renegotiation tests for renegotiation vulnerabilities
@@ -23950,7 +23992,7 @@ set_rating_state() {
2395023992

2395123993
# All of these should be enabled
2395223994
for gbl in do_protocols do_cipherlists do_fs do_server_defaults do_header \
23953-
do_heartbleed do_ccs_injection do_ticketbleed do_robot do_renego \
23995+
do_heartbleed do_ccs_injection do_ticketbleed do_opossum do_robot do_renego \
2395423996
do_crime do_ssl_poodle do_tls_fallback_scsv do_drown do_beast \
2395523997
do_rc4 do_logjam; do
2395623998
"${!gbl}" && ((nr_enabled++))
@@ -23980,6 +24022,7 @@ initialize_globals() {
2398024022
do_breach=false
2398124023
do_ccs_injection=false
2398224024
do_ticketbleed=false
24025+
do_opossum=false
2398324026
do_robot=false
2398424027
do_cipher_per_proto=false
2398524028
do_crime=false
@@ -24028,6 +24071,7 @@ set_scanning_defaults() {
2402824071
do_heartbleed="$OFFENSIVE"
2402924072
do_ccs_injection="$OFFENSIVE"
2403024073
do_ticketbleed="$OFFENSIVE"
24074+
do_opossum=true
2403124075
do_robot="$OFFENSIVE"
2403224076
do_crime=true
2403324077
do_freak=true
@@ -24048,9 +24092,9 @@ set_scanning_defaults() {
2404824092
do_tls_fallback_scsv=true
2404924093
do_client_simulation=true
2405024094
if "$OFFENSIVE"; then
24051-
VULN_COUNT=17
24095+
VULN_COUNT=18
2405224096
else
24053-
VULN_COUNT=13
24097+
VULN_COUNT=14
2405424098
fi
2405524099
do_rating=true
2405624100
}
@@ -24061,10 +24105,10 @@ count_do_variables() {
2406124105
local -i true_nr=0
2406224106

2406324107
for gbl in do_allciphers do_vulnerabilities do_beast do_lucky13 do_breach do_ccs_injection do_ticketbleed do_cipher_per_proto do_crime \
24064-
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 \
24065-
do_cipherlists do_server_defaults do_server_preference do_ssl_poodle do_tls_fallback_scsv do_winshock \
24066-
do_sweet32 do_client_simulation do_cipher_match do_tls_sockets do_mass_testing do_display_only do_rating; do
24067-
"${!gbl}" && ((true_nr++))
24108+
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 \
24109+
do_opossum do_robot do_renego do_cipherlists do_server_defaults do_server_preference do_ssl_poodle do_tls_fallback_scsv \
24110+
do_winshock do_sweet32 do_client_simulation do_cipher_match do_tls_sockets do_mass_testing do_display_only do_rating; do
24111+
"${!gbl}" && ((true_nr++))
2406824112
done
2406924113
return $true_nr
2407024114
}
@@ -24074,10 +24118,10 @@ debug_globals() {
2407424118
local gbl
2407524119

2407624120
for gbl in do_allciphers do_vulnerabilities do_beast do_lucky13 do_breach do_ccs_injection do_ticketbleed do_cipher_per_proto do_crime \
24077-
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 \
24078-
do_cipherlists do_server_defaults do_server_preference do_ssl_poodle do_tls_fallback_scsv do_winshock \
24079-
do_sweet32 do_client_simulation do_cipher_match do_tls_sockets do_mass_testing do_display_only do_rating; do
24080-
printf "%-22s = %s\n" $gbl "${!gbl}"
24121+
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\
24122+
do_opossum do_robot do_renego do_cipherlists do_server_defaults do_server_preference do_ssl_poodle do_tls_fallback_scsv \
24123+
do_winshock do_sweet32 do_client_simulation do_cipher_match do_tls_sockets do_mass_testing do_display_only do_rating; do
24124+
printf "%-22s = %s\n" $gbl "${!gbl}"
2408124125
done
2408224126
# ${!var} is an indirect expansion, see https://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html
2408324127
# Example: https://stackoverflow.com/questions/8515411/what-is-indirect-expansion-what-does-var-mean#8515492
@@ -24283,6 +24327,7 @@ parse_cmd_line() {
2428324327
do_heartbleed="$OFFENSIVE"
2428424328
do_ccs_injection="$OFFENSIVE"
2428524329
do_ticketbleed="$OFFENSIVE"
24330+
do_opossum=true
2428624331
do_robot="$OFFENSIVE"
2428724332
do_renego=true
2428824333
do_crime=true
@@ -24299,9 +24344,9 @@ parse_cmd_line() {
2429924344
do_rc4=true
2430024345
do_starttls_injection=true
2430124346
if "$OFFENSIVE"; then
24302-
VULN_COUNT=17
24347+
VULN_COUNT=18
2430324348
else
24304-
VULN_COUNT=13
24349+
VULN_COUNT=14
2430524350
fi
2430624351
;;
2430724352
--ids-friendly)
@@ -24319,6 +24364,10 @@ parse_cmd_line() {
2431924364
do_ticketbleed=true
2432024365
((VULN_COUNT++))
2432124366
;;
24367+
--OP|--opossum)
24368+
do_opossum=true
24369+
((VULN_COUNT++))
24370+
;;
2432224371
-BB|--BB|--robot)
2432324372
do_robot=true
2432424373
;;
@@ -24984,6 +25033,7 @@ lets_roll() {
2498425033
"$do_heartbleed" && { run_heartbleed; ret=$(($? + ret)); stopwatch run_heartbleed; }
2498525034
"$do_ccs_injection" && { run_ccs_injection; ret=$(($? + ret)); stopwatch run_ccs_injection; }
2498625035
"$do_ticketbleed" && { run_ticketbleed; ret=$(($? + ret)); stopwatch run_ticketbleed; }
25036+
"$do_opossum" && { run_opossum; ret=$(($? + ret)); stopwatch run_opossum; }
2498725037
"$do_robot" && { run_robot; ret=$(($? + ret)); stopwatch run_robot; }
2498825038
"$do_renego" && { run_renego; ret=$(($? + ret)); stopwatch run_renego; }
2498925039
"$do_crime" && { run_crime; ret=$(($? + ret)); stopwatch run_crime; }

0 commit comments

Comments
 (0)