mirror of
https://github.com/drwetter/testssl.sh.git
synced 2025-06-17 20:48:35 +02:00
Detect downgrade to plaintext for STARTTLS, IMAP
Some Cyrus IMAD if configured with SSL_CTX_set_cipher_list(context, "!TLSv1") and similar respond with a plaintext 'a002 NO Starttls negotiation failed" when a not-supported protocol is detected, see #1082. This PR fixes this by detecting (also) this downgrade. As a precaution It still issues a warning as this is seems a special configuration.
This commit is contained in:
parent
43ee837ec2
commit
987fbeda37
79
testssl.sh
79
testssl.sh
@ -4889,6 +4889,12 @@ run_protocols() {
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
|
3) pr_svrty_best "not offered (OK), "
|
||||||
|
fileout "$jsonID" "OK" "not offered"
|
||||||
|
add_tls_offered ssl3 no
|
||||||
|
pr_warning "SSL downgraded to STARTTLS plaintext"; outln
|
||||||
|
fileout "$jsonID" "WARN" "SSL downgraded to STARTTLS plaintext"
|
||||||
|
;;
|
||||||
4) out "likely "; pr_svrty_best "not offered (OK), "
|
4) out "likely "; pr_svrty_best "not offered (OK), "
|
||||||
fileout "$jsonID" "OK" "not offered"
|
fileout "$jsonID" "OK" "not offered"
|
||||||
add_tls_offered ssl3 no
|
add_tls_offered ssl3 no
|
||||||
@ -4956,6 +4962,12 @@ run_protocols() {
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
|
3) out "not offered, "
|
||||||
|
fileout "$jsonID" "OK" "not offered"
|
||||||
|
add_tls_offered tls1 no
|
||||||
|
pr_warning "TLS downgraded to STARTTLS plaintext"; outln
|
||||||
|
fileout "$jsonID" "WARN" "TLS downgraded to STARTTLS plaintext"
|
||||||
|
;;
|
||||||
4) out "likely not offered, "
|
4) out "likely not offered, "
|
||||||
fileout "$jsonID" "INFO" "likely not offered"
|
fileout "$jsonID" "INFO" "likely not offered"
|
||||||
add_tls_offered tls1 no
|
add_tls_offered tls1 no
|
||||||
@ -5027,6 +5039,12 @@ run_protocols() {
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
|
3) out "not offered, "
|
||||||
|
fileout "$jsonID" "OK" "not offered"
|
||||||
|
add_tls_offered tls1_1 no
|
||||||
|
pr_warning "TLS downgraded to STARTTLS plaintext"; outln
|
||||||
|
fileout "$jsonID" "WARN" "TLS downgraded to STARTTLS plaintext"
|
||||||
|
;;
|
||||||
4) out "likely not offered, "
|
4) out "likely not offered, "
|
||||||
fileout "$jsonID" "INFO" "is not offered"
|
fileout "$jsonID" "INFO" "is not offered"
|
||||||
add_tls_offered tls1_1 no
|
add_tls_offered tls1_1 no
|
||||||
@ -5109,17 +5127,23 @@ run_protocols() {
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
4) out "likely "; pr_svrty_medium "not offered, "
|
3) out "not offered, "
|
||||||
|
fileout "$jsonID" "OK" "not offered"
|
||||||
|
add_tls_offered tls1_2 no
|
||||||
|
pr_warning "TLS downgraded to STARTTLS plaintext"; outl
|
||||||
|
fileout "$jsonID" "WARN" "TLS downgraded to STARTTLS plaintext"
|
||||||
|
;;
|
||||||
|
4) out "likely "; pr_svrty_medium "not offered, "
|
||||||
fileout "$jsonID" "MEDIUM" "not offered"
|
fileout "$jsonID" "MEDIUM" "not offered"
|
||||||
add_tls_offered tls1_2 no
|
add_tls_offered tls1_2 no
|
||||||
pr_warning "received 4xx/5xx after STARTTLS handshake"; outln "$debug_recomm"
|
pr_warning "received 4xx/5xx after STARTTLS handshake"; outln "$debug_recomm"
|
||||||
fileout "$jsonID" "WARN" "received 4xx/5xx after STARTTLS handshake${debug_recomm}"
|
fileout "$jsonID" "WARN" "received 4xx/5xx after STARTTLS handshake${debug_recomm}"
|
||||||
;;
|
;;
|
||||||
5) outln "$supported_no_ciph1" # protocol detected, but no cipher --> comes from run_prototest_openssl
|
5) outln "$supported_no_ciph1" # protocol detected, but no cipher --> comes from run_prototest_openssl
|
||||||
fileout "$jsonID" "INFO" "$supported_no_ciph1"
|
fileout "$jsonID" "INFO" "$supported_no_ciph1"
|
||||||
add_tls_offered tls1_2 yes
|
add_tls_offered tls1_2 yes
|
||||||
;;
|
;;
|
||||||
7) if "$using_sockets" ; then
|
7) if "$using_sockets" ; then
|
||||||
# can only happen in debug mode
|
# can only happen in debug mode
|
||||||
pr_warning "strange reply, maybe a client side problem with TLS 1.2"; outln "$debug_recomm"
|
pr_warning "strange reply, maybe a client side problem with TLS 1.2"; outln "$debug_recomm"
|
||||||
else
|
else
|
||||||
@ -5277,6 +5301,12 @@ run_protocols() {
|
|||||||
fi
|
fi
|
||||||
add_tls_offered tls1_3 no
|
add_tls_offered tls1_3 no
|
||||||
;;
|
;;
|
||||||
|
3) out "not offered "
|
||||||
|
fileout "$jsonID" "INFO" "not offered"
|
||||||
|
add_tls_offered tls1_3 no
|
||||||
|
pr_warning "TLS downgraded to STARTTLS plaintext"; outln
|
||||||
|
fileout "$jsonID" "WARN" "TLS downgraded to STARTTLS plaintext"
|
||||||
|
;;
|
||||||
4) out "likely not offered, "
|
4) out "likely not offered, "
|
||||||
fileout "$jsonID" "INFO" "not offered"
|
fileout "$jsonID" "INFO" "not offered"
|
||||||
add_tls_offered tls1_3 no
|
add_tls_offered tls1_3 no
|
||||||
@ -9164,13 +9194,16 @@ starttls_mysql_dialog() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# arg1: fd for socket -- which we don't use as it is a hassle and it is not clear whether it works under every bash version
|
# arg1: fd for socket -- which we don't use as it is a hassle and it is not clear whether it works under every bash version
|
||||||
#
|
# returns 6 if opening the socket caused a problem, 1 if STARTTLS handshake failed, 0: all ok
|
||||||
fd_socket() {
|
fd_socket() {
|
||||||
local jabber=""
|
local jabber=""
|
||||||
local proyxline=""
|
local proyxline=""
|
||||||
local nodeip="$(tr -d '[]' <<< $NODEIP)" # sockets do not need the square brackets we have of IPv6 addresses
|
local nodeip="$(tr -d '[]' <<< $NODEIP)" # sockets do not need the square brackets we have of IPv6 addresses
|
||||||
# we just need do it here, that's all!
|
# we just need do it here, that's all!
|
||||||
[[ -t 5 ]] && echo "tty"
|
if [[ -t 5 ]]; then
|
||||||
|
pr_warning "$PROG_NAME: unable to open a socket because of a tty conflict"
|
||||||
|
return 6
|
||||||
|
fi
|
||||||
if [[ -n "$PROXY" ]]; then
|
if [[ -n "$PROXY" ]]; then
|
||||||
# PROXYNODE works better than PROXYIP on modern versions of squid
|
# PROXYNODE works better than PROXYIP on modern versions of squid
|
||||||
if ! exec 5<> /dev/tcp/${PROXYNODE}/${PROXYPORT}; then
|
if ! exec 5<> /dev/tcp/${PROXYNODE}/${PROXYPORT}; then
|
||||||
@ -9607,7 +9640,7 @@ get_dh_ephemeralkey() {
|
|||||||
# 3=SSLv2 supported (in $TEMPDIR/$NODEIP.sslv2_sockets.dd is reply for further processing
|
# 3=SSLv2 supported (in $TEMPDIR/$NODEIP.sslv2_sockets.dd is reply for further processing
|
||||||
# --> there could be checked whether ciphers e.g have been returned at all (or anything else)
|
# --> there could be checked whether ciphers e.g have been returned at all (or anything else)
|
||||||
# 4=looks like an STARTTLS 5xx message
|
# 4=looks like an STARTTLS 5xx message
|
||||||
# 6=socket coudln't be opened
|
# 6=socket couldn't be opened
|
||||||
# 7=strange reply we can't deal with
|
# 7=strange reply we can't deal with
|
||||||
parse_sslv2_serverhello() {
|
parse_sslv2_serverhello() {
|
||||||
local ret v2_hello_ascii v2_hello_initbyte v2_hello_length
|
local ret v2_hello_ascii v2_hello_initbyte v2_hello_length
|
||||||
@ -10572,7 +10605,7 @@ parse_tls_serverhello() {
|
|||||||
fi
|
fi
|
||||||
for (( i=0; i<tls_hello_ascii_len; i=i+msg_len )); do
|
for (( i=0; i<tls_hello_ascii_len; i=i+msg_len )); do
|
||||||
if [[ $tls_hello_ascii_len-$i -lt 10 ]]; then
|
if [[ $tls_hello_ascii_len-$i -lt 10 ]]; then
|
||||||
if [[ "$process_full" == "all" ]]; then
|
if [[ "$process_full" == all ]]; then
|
||||||
# The entire server response should have been retrieved.
|
# The entire server response should have been retrieved.
|
||||||
debugme tmln_warning "Malformed message."
|
debugme tmln_warning "Malformed message."
|
||||||
[[ $DEBUG -ge 1 ]] && tmpfile_handle ${FUNCNAME[0]}.txt
|
[[ $DEBUG -ge 1 ]] && tmpfile_handle ${FUNCNAME[0]}.txt
|
||||||
@ -10604,13 +10637,19 @@ parse_tls_serverhello() {
|
|||||||
tmln_out
|
tmln_out
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if "$do_starttls" && ( [[ $tls_content_type == 35 ]] || [[ $tls_content_type == 34 ]] ); then
|
if "$do_starttls" ; then
|
||||||
# STARTTLS handshake failed and server replied plaintext with a 5xx or 4xx
|
if [[ $tls_content_type == 35 ]] || [[ $tls_content_type == 34 ]]; then
|
||||||
[[ $DEBUG -ge 2 ]] && printf "%s\n" "$(hex2ascii "$tls_hello_ascii" 2>/dev/null)"
|
# STARTTLS handshake failed and server replied plaintext with a 5xx or 4xx
|
||||||
[[ $DEBUG -ge 1 ]] && tmpfile_handle ${FUNCNAME[0]}.txt
|
[[ $DEBUG -ge 2 ]] && printf "%s\n" "400/500: $(hex2ascii "$tls_hello_ascii" 2>/dev/null)"
|
||||||
return 4
|
[[ $DEBUG -ge 1 ]] && tmpfile_handle ${FUNCNAME[0]}.txt
|
||||||
elif [[ $tls_content_type != "14" ]] && [[ $tls_content_type != "15" ]] && \
|
return 4
|
||||||
[[ $tls_content_type != "16" ]] && [[ $tls_content_type != "17" ]]; then
|
elif [[ "$tls_hello_ascii" =~ 6130303220 ]]; then
|
||||||
|
[[ $DEBUG -ge 2 ]] && printf "%s\n" "probably IMAP plaintext reply \"$(hex2ascii "${tls_hello_ascii:0:32}" 2>/dev/null)\""
|
||||||
|
[[ $DEBUG -ge 1 ]] && tmpfile_handle ${FUNCNAME[0]}.txt
|
||||||
|
return 3
|
||||||
|
fi
|
||||||
|
elif [[ $tls_content_type != 14 ]] && [[ $tls_content_type != 15 ]] && \
|
||||||
|
[[ $tls_content_type != 16 ]] && [[ $tls_content_type != 17 ]]; then
|
||||||
debugme tmln_warning "Content type other than alert, handshake, change cipher spec, or application data detected."
|
debugme tmln_warning "Content type other than alert, handshake, change cipher spec, or application data detected."
|
||||||
[[ $DEBUG -ge 1 ]] && tmpfile_handle ${FUNCNAME[0]}.txt
|
[[ $DEBUG -ge 1 ]] && tmpfile_handle ${FUNCNAME[0]}.txt
|
||||||
return 8
|
return 8
|
||||||
@ -10622,7 +10661,7 @@ parse_tls_serverhello() {
|
|||||||
DETECTED_TLS_VERSION=$tls_protocol
|
DETECTED_TLS_VERSION=$tls_protocol
|
||||||
|
|
||||||
if [[ $msg_len -gt $tls_hello_ascii_len-$i ]]; then
|
if [[ $msg_len -gt $tls_hello_ascii_len-$i ]]; then
|
||||||
if [[ "$process_full" == "all" ]]; then
|
if [[ "$process_full" == all ]]; then
|
||||||
debugme tmln_warning "Malformed message."
|
debugme tmln_warning "Malformed message."
|
||||||
[[ $DEBUG -ge 1 ]] && tmpfile_handle ${FUNCNAME[0]}.txt
|
[[ $DEBUG -ge 1 ]] && tmpfile_handle ${FUNCNAME[0]}.txt
|
||||||
return 7
|
return 7
|
||||||
@ -10642,7 +10681,7 @@ parse_tls_serverhello() {
|
|||||||
|
|
||||||
# Now check the alert messages.
|
# Now check the alert messages.
|
||||||
tls_alert_ascii_len=${#tls_alert_ascii}
|
tls_alert_ascii_len=${#tls_alert_ascii}
|
||||||
if [[ "$process_full" == "all" ]] && [[ $tls_alert_ascii_len%4 -ne 0 ]]; then
|
if [[ "$process_full" == all ]] && [[ $tls_alert_ascii_len%4 -ne 0 ]]; then
|
||||||
debugme tmln_warning "Malformed message."
|
debugme tmln_warning "Malformed message."
|
||||||
[[ $DEBUG -ge 1 ]] && tmpfile_handle ${FUNCNAME[0]}.txt
|
[[ $DEBUG -ge 1 ]] && tmpfile_handle ${FUNCNAME[0]}.txt
|
||||||
return 1
|
return 1
|
||||||
@ -10706,7 +10745,6 @@ parse_tls_serverhello() {
|
|||||||
i=$i+2
|
i=$i+2
|
||||||
msg_len=2*$(hex2dec "${tls_handshake_ascii:i:6}")
|
msg_len=2*$(hex2dec "${tls_handshake_ascii:i:6}")
|
||||||
i=$i+6
|
i=$i+6
|
||||||
|
|
||||||
if [[ $DEBUG -ge 3 ]]; then
|
if [[ $DEBUG -ge 3 ]]; then
|
||||||
tm_out " handshake type: 0x${tls_msg_type}"
|
tm_out " handshake type: 0x${tls_msg_type}"
|
||||||
case $tls_msg_type in
|
case $tls_msg_type in
|
||||||
@ -11602,6 +11640,7 @@ parse_tls_serverhello() {
|
|||||||
|
|
||||||
#arg1: list of ciphers suites or empty
|
#arg1: list of ciphers suites or empty
|
||||||
#arg2: "true" if full server response should be parsed.
|
#arg2: "true" if full server response should be parsed.
|
||||||
|
# return: 6: couldn't open socket, 0: OK, else: return value of parse_sslv2_serverhello()
|
||||||
sslv2_sockets() {
|
sslv2_sockets() {
|
||||||
local ret
|
local ret
|
||||||
local client_hello cipher_suites len_client_hello
|
local client_hello cipher_suites len_client_hello
|
||||||
@ -12447,7 +12486,7 @@ tls_sockets() {
|
|||||||
# if the ephemeral key is needed (which comes last for TLS 1.2 and
|
# if the ephemeral key is needed (which comes last for TLS 1.2 and
|
||||||
# below), then we need to check if response appears to be complete,
|
# below), then we need to check if response appears to be complete,
|
||||||
# and if it isn't then try to get another packet from the server.
|
# and if it isn't then try to get another packet from the server.
|
||||||
if [[ "$process_full" == "all" ]] || [[ "$process_full" == "ephemeralkey" ]]; then
|
if [[ "$process_full" == all ]] || [[ "$process_full" == ephemeralkey ]]; then
|
||||||
hello_done=1; skip=true
|
hello_done=1; skip=true
|
||||||
fi
|
fi
|
||||||
for (( 1 ; hello_done==1; 1 )); do
|
for (( 1 ; hello_done==1; 1 )); do
|
||||||
@ -12473,7 +12512,6 @@ tls_sockets() {
|
|||||||
hello_done=0
|
hello_done=0
|
||||||
else
|
else
|
||||||
tls_hello_ascii+="$next_packet"
|
tls_hello_ascii+="$next_packet"
|
||||||
|
|
||||||
if [[ $DEBUG -ge 1 ]]; then
|
if [[ $DEBUG -ge 1 ]]; then
|
||||||
sock_reply_file3=$(mktemp $TEMPDIR/ddreply.XXXXXX) || return 7
|
sock_reply_file3=$(mktemp $TEMPDIR/ddreply.XXXXXX) || return 7
|
||||||
mv "$SOCK_REPLY_FILE" "$sock_reply_file3"
|
mv "$SOCK_REPLY_FILE" "$sock_reply_file3"
|
||||||
@ -12535,6 +12573,9 @@ tls_sockets() {
|
|||||||
# determine the return value for higher level, so that they can tell what the result is
|
# determine the return value for higher level, so that they can tell what the result is
|
||||||
if [[ $save -eq 1 ]] || [[ $lines -eq 1 ]]; then
|
if [[ $save -eq 1 ]] || [[ $lines -eq 1 ]]; then
|
||||||
ret=1 # NOT available
|
ret=1 # NOT available
|
||||||
|
elif [[ $save -eq 3 ]]; then
|
||||||
|
# only for IMAP currently 'a002 NO Starttls'
|
||||||
|
ret=3
|
||||||
elif [[ $save -eq 8 ]]; then
|
elif [[ $save -eq 8 ]]; then
|
||||||
# odd return, we just pass this from parse_tls_serverhello() back
|
# odd return, we just pass this from parse_tls_serverhello() back
|
||||||
ret=8
|
ret=8
|
||||||
|
Loading…
x
Reference in New Issue
Block a user