Fix and improve Opossum

Under some circumstances the opossum vulnerability check got stuck
because the cat commdn was waiting for reading from the descriptor.
In some case like #2950 this happened when the HTTP head command
was incorrectly send in the first place.

This PR makes sure that the HTTP head is correct and it replaces
cat by read in a loop so that the HTTP response is read without
being blocked.

Also for http_head_printf() the argumensats passed were cleaned up.
This commit is contained in:
Dirk
2025-11-19 20:55:20 +01:00
parent ae48b680fa
commit 76824b5762

View File

@@ -1939,26 +1939,25 @@ http_head() {
} }
# does a simple http head via printf with no proxy, only used by run_opossum() # does a simple http head via printf with no proxy, only used by run_opossum()
# arg1: URL # arg1: extra http header
# arg2: extra http header
# #
# return codes: # return codes:
# 0: all fine (response header is returned as string) # 0: all fine (response header is returned as string)
# 1: server didn't respond within HEADER_MAXSLEEP # 1: server didn't respond within HEADER_MAXSLEEP
# 3: server didn't respond within HEADER_MAXSLEEP and PROXY was defined # 3: server didn't respond within HEADER_MAXSLEEP and PROXY was defined
# #
# return http header as string
#
http_head_printf() { http_head_printf() {
local request_header="$2" local node="$NODE"
local path="$URL_PATH"
local extra_header="$1"
local useragent="$UA_STD" local useragent="$UA_STD"
local tmpfile=$TEMPDIR/$NODE.$NODEIP.http_head_printf.log local tmpfile=$TEMPDIR/$NODE.$NODEIP.http_head_printf.log
local errfile=$TEMPDIR/$NODE.$NODEIP.http_head_printf-err.log local errfile=$TEMPDIR/$NODE.$NODEIP.http_head_printf-err.log
local -i ret=0 local -i ret=0
local proto="" foo="" node="" query=""
[[ $DEBUG -eq 0 ]] && errfile=/dev/null [[ $DEBUG -eq 0 ]] && errfile=/dev/null
IFS=/ read -r proto foo node query <<< "$1"
node=${node%:*}
# $node works here good as it connects via IPv6 first, then IPv4. # $node works here good as it connects via IPv6 first, then IPv4.
# This is a subshell, so fd 8 is not inherited # This is a subshell, so fd 8 is not inherited
bash -c "exec 8<>/dev/tcp/$node/80" 2>/dev/null & bash -c "exec 8<>/dev/tcp/$node/80" 2>/dev/null &
@@ -1969,14 +1968,16 @@ http_head_printf() {
bash -c "exec 8<>/dev/tcp/$node/80" 2>/dev/null bash -c "exec 8<>/dev/tcp/$node/80" 2>/dev/null
if [[ $? -eq 0 ]]; then if [[ $? -eq 0 ]]; then
exec 33<>/dev/tcp/$node/80 exec 33<>/dev/tcp/$node/80
# not killed --> socket open. Now we connect to the virtual host "$node" safe_echo "HEAD ${path} HTTP/1.1\r\nUser-Agent: ${useragent}\r\nHost: ${node}\r\nAccept: */*\r\n${extra_header}\r\n\r\n" >&33 2>$errfile
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
ret=0 ret=0
if [[ $DEBUG -eq 0 ]] ; then touch $tmpfile
cat <&33 # This doesn't block
else while IFS= read -r line <&33; do
cat <&33 >$tmpfile safe_echo "$line" >>$tmpfile
cat $tmpfile done
cat $tmpfile
if [[ $DEBUG -ge 2 ]]; then
cat $tmpfile >&2
fi fi
else else
if [[ -n "$PROXY" ]]; then if [[ -n "$PROXY" ]]; then
@@ -8054,10 +8055,10 @@ determine_trust() {
out "$code" out "$code"
fi fi
fileout "${jsonID}${json_postfix}" "CRITICAL" "failed $code. $addtl_warning" fileout "${jsonID}${json_postfix}" "CRITICAL" "failed $code. $addtl_warning"
if [[ "$code" =~ "chain incomplete" ]]; then if [[ "$code" =~ "chain incomplete" ]]; then
set_grade_cap "B" "Issues with chain of trust $code" set_grade_cap "B" "Issues with chain of trust $code"
else else
set_grade_cap "T" "Issues with chain of trust $code" set_grade_cap "T" "Issues with chain of trust $code"
fi fi
else else
# alt least one ok and other(s) not ==> display the culprit store(s) # alt least one ok and other(s) not ==> display the culprit store(s)
@@ -17860,6 +17861,8 @@ run_ticketbleed() {
} }
# https://opossum-attack.com/, TLS Upgrade via old RFC 2817 # https://opossum-attack.com/, TLS Upgrade via old RFC 2817
# TL;DR: curl -vi -I -H "Upgrade: TLS/1.0" <FQDN> --> returns "Upgrade: TLS/1.0"?
# We might be better off with cURL but sockets are sometimes better
# #
run_opossum() { run_opossum() {
local cve='CVE-2025-49812' local cve='CVE-2025-49812'
@@ -17881,8 +17884,7 @@ run_opossum() {
fi fi
case $service in case $service in
HTTP) HTTP)
uri=${URI/https:\/\//} response=$(http_head_printf 'Upgrade: TLS/1.0')
response=$(http_head_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 # In any case we use $response but we handle the return codes
# 0: connection was fine, 1 or 3: no http connection # 0: connection was fine, 1 or 3: no http connection
ret=$? ret=$?
@@ -17904,6 +17906,7 @@ run_opossum() {
fi fi
fi fi
;; ;;
IMAP|FTP|POP3|SMTP|LMTP|NNTP) IMAP|FTP|POP3|SMTP|LMTP|NNTP)
outln "(implemented currently for HTTP only)" outln "(implemented currently for HTTP only)"
fileout "$jsonID" "INFO" "not yet implemented" "$cve" "$cwe" fileout "$jsonID" "INFO" "not yet implemented" "$cve" "$cwe"