Skip to content

Commit eb49c37

Browse files
committed
* EXPERIMETAL=yes is used, testssl.sh uses for protocols, heartbleed, ccs sockets also for STARTTLS!
* it's slow though (to be improved) * renamed vars for proxy * cleanups
1 parent 5fe9cf7 commit eb49c37

File tree

1 file changed

+139
-42
lines changed

1 file changed

+139
-42
lines changed

testssl.sh

+139-42
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ HEADER_MAXSLEEP=${HEADER_MAXSLEEP:-5} # we wait this long before killing the pro
114114
readonly MAX_WAITSOCK=10 # waiting at max 10 seconds for socket reply
115115
readonly CCS_MAX_WAITSOCK=5 # for the two CCS payload (each)
116116
readonly HEARTBLEED_MAX_WAITSOCK=8 # for the heartbleed payload
117+
readonly STARTTLS_SLEEP=1 # max time to wait on a socket replay for STARTTLS
117118
USLEEP_SND=${USLEEP_SND:-0.1} # sleep time for general socket send
118119
USLEEP_REC=${USLEEP_REC:-0.2} # sleep time for general socket receive
119120

@@ -415,22 +416,22 @@ tmpfile_handle() {
415416
fi
416417
}
417418

418-
# ARG1= pid which is in the backgnd and we wait for ($2 seconds)
419419
wait_kill(){
420-
pid=$1
421-
maxsleep=$2
420+
local pid=$1 # pid we wait for or kill
421+
local maxsleep=$2 # how long we wait before killing
422+
422423
while true; do
424+
[[ "$DEBUG" -ge 6 ]] && ps $pid
423425
if ! ps $pid >/dev/null ; then
424-
return 0 # didn't reach maxsleep yet
426+
return 0 # process terminated before didn't reach $maxsleep
425427
fi
426428
sleep 1
427429
maxsleep=$((maxsleep - 1))
428-
test $maxsleep -eq 0 && break
429-
done # needs to be killed:
430+
test $maxsleep -le 0 && break
431+
done # needs to be killed:
430432
kill $pid >&2 2>/dev/null
431-
wait $pid 2>/dev/null
432-
#FIXME: do we need wait here???? normally it's good to report the exit status?!
433-
return 3 # killed
433+
wait $pid 2>/dev/null # make sure pid terminated, see wait(1p)
434+
return 3 # means killed
434435
}
435436

436437

@@ -508,8 +509,7 @@ Connection: close
508509
509510
EOF
510511
) &>$HEADERFILE &
511-
pid=$!
512-
if wait_kill $pid $HEADER_MAXSLEEP; then
512+
if wait_kill $! $HEADER_MAXSLEEP; then
513513
if ! egrep -iaq "XML|HTML|DOCTYPE|HTTP|Connection" $HEADERFILE; then
514514
pr_litemagenta " likely HTTP header requests failed (#lines: $(wc -l < $HEADERFILE | sed 's/ //g'))."
515515
outln "Rerun with DEBUG=1 and inspect \"http_header.txt\"\n"
@@ -1042,9 +1042,7 @@ sockread() {
10421042

10431043
ddreply=$(mktemp $TEMPDIR/ddreply.XXXXXX) || return 7
10441044
dd bs=$1 of=$ddreply count=1 <&5 2>/dev/null &
1045-
pid=$!
1046-
1047-
wait_kill $pid $maxsleep
1045+
wait_kill $! $maxsleep
10481046
ret=$?
10491047
SOCKREPLY=$(cat $ddreply)
10501048
rm $ddreply
@@ -1268,7 +1266,7 @@ run_protocols() {
12681266

12691267
pr_blue "--> Testing protocols ";
12701268

1271-
if $SSL_NATIVE || [ -n "$STARTTLS" ]; then
1269+
if $SSL_NATIVE || [ -n "$STARTTLS" ] && [[ $EXPERIMENTAL != "yes" ]]; then
12721270
using_sockets=false
12731271
outln "(via native openssl)\n"
12741272
else
@@ -1939,7 +1937,7 @@ spdy_pre(){
19391937
fi
19401938
if [ ! -z "$PROXY" ]; then
19411939
[ -n "$1" ] && pr_litemagenta "$1 "
1942-
pr_litemagenta "not being tested as proxies do not support it"
1940+
pr_litemagenta "not tested as proxies do not support proxying it"
19431941
return 1
19441942
fi
19451943
# first, does the current openssl support it?
@@ -1979,8 +1977,52 @@ run_spdy() {
19791977
return $ret
19801978
}
19811979

1980+
1981+
# arg1: string to send
1982+
# arg2: possible success strings a egrep pattern, needed!
1983+
starttls_line() {
1984+
debugme echo -e "\n=== sending \"$1\" ..."
1985+
echo -e "$1" >&5
1986+
1987+
# we don't know how much to read and it's blocking! So we just put a cat into the
1988+
# background and read until $STARTTLS_SLEEP and: cross our fingers
1989+
cat <&5 >$TMPFILE &
1990+
wait_kill $! $STARTTLS_SLEEP
1991+
debugme echo "... received result: "
1992+
debugme cat $TMPFILE
1993+
if [ -n "$2" ]; then
1994+
if egrep -q "$2" $TMPFILE; then
1995+
debugme echo "---> reply matched \"$2\""
1996+
else
1997+
debugme echo "---> reply didn't match \"$2\", see $TMPFILE"
1998+
pr_magenta "STARTTLS handshake problem."
1999+
outln "Please recheck your cmdline and/or debug what happened ($PROG_NAME --debug=2 <cmdline>)."
2000+
exit 1
2001+
fi
2002+
fi
2003+
2004+
return 0
2005+
}
2006+
2007+
starttls_just_read(){
2008+
debugme echo "=== just read banner ==="
2009+
if [[ "$DEBUG" -ge 2 ]] ; then
2010+
cat <&5 &
2011+
wait_kill $! $STARTTLS_SLEEP
2012+
else
2013+
dd of=/dev/null count=8 <&5 2>/dev/null &
2014+
wait_kill $! $STARTTLS_SLEEP
2015+
fi
2016+
2017+
return 0
2018+
}
2019+
2020+
19822021
# arg for a fd doesn't work here
19832022
fd_socket() {
2023+
local jabber=""
2024+
local proyxline=""
2025+
19842026
if [[ -n "$PROXY" ]]; then
19852027
if ! exec 5<> /dev/tcp/${PROXYIP}/${PROXYPORT}; then
19862028
outln
@@ -1989,25 +2031,80 @@ fd_socket() {
19892031
fi
19902032
echo "CONNECT $NODEIP:$PORT" >&5
19912033
while true ; do
1992-
read x <&5
1993-
if [[ "${x%/*}" == "HTTP" ]]; then
1994-
x=${x#* }
1995-
if [[ "${x%% *}" != "200" ]] ; then
2034+
read proyxline <&5
2035+
if [[ "${proyxline%/*}" == "HTTP" ]]; then
2036+
proyxline=${proyxline#* }
2037+
if [[ "${proyxline%% *}" != "200" ]] ; then
19962038
[[ "$PORT" != 443 ]] && outln "Check whether your proxy supports port $PORT and the underlying protocol."
19972039
pr_magenta "Unable to CONNECT via proxy. "
19982040
return 6
19992041
fi
20002042
fi
2001-
if [[ "$x" == $'\r' ]] ; then
2043+
if [[ "$proyxline" == $'\r' ]] ; then
20022044
break
20032045
fi
20042046
done
2005-
elif ! exec 5<>/dev/tcp/$NODEIP/$PORT; then # 2>/dev/null removes an error message, but disables debugging
2047+
elif ! exec 5<>/dev/tcp/$NODEIP/$PORT; then # 2>/dev/null would remove an error message, but disables debugging
20062048
outln
2007-
pr_magenta "Unable to open a socket to $NODEIP:$PORT. "
2049+
pr_magentaln "Unable to open a socket to $NODEIP:$PORT. "
20082050
# It can last ~2 minutes but for for those rare occasions we don't do a timeout handler here, KISS
20092051
return 6
20102052
fi
2053+
2054+
if [[ -n "$STARTTLS" ]]; then
2055+
case "$PORT" in # port
2056+
21) # https://tools.ietf.org/html/rfc4217
2057+
starttls_just_read
2058+
starttls_line "FEAT" "211"
2059+
starttls_line "AUTH TLS" "successful|234"
2060+
;;
2061+
25) # SMTP, see https://tools.ietf.org/html/rfc4217
2062+
starttls_just_read
2063+
starttls_line "EHLO testssl.sh" "220|250"
2064+
starttls_line "STARTTLS" "220"
2065+
;;
2066+
110) # POP, see https://tools.ietf.org/html/rfc2595
2067+
starttls_just_read
2068+
starttls_line "STLS" "OK"
2069+
;;
2070+
119|433) # NNTP, see https://tools.ietf.org/html/rfc4642
2071+
starttls_just_read
2072+
starttls_line "CAPABILITIES" "101|200"
2073+
starttls_line "STARTTLS" "382"
2074+
;;
2075+
143) # IMAP, https://tools.ietf.org/html/rfc2595
2076+
starttls_just_read
2077+
starttls_line "a001 CAPABILITY" "OK"
2078+
starttls_line "a002 STARTTLS" "OK"
2079+
;;
2080+
389) # LDAP, https://tools.ietf.org/html/rfc2830, https://tools.ietf.org/html/rfc4511
2081+
pr_magentaln "FIXME: LDAP/STARTTLS not yet supported"
2082+
exit 1
2083+
;;
2084+
674) # ACAP = Application Configuration Access Protocol, see https://tools.ietf.org/html/rfc2595
2085+
pr_magentaln "ACAP Easteregg: not implemented -- probably never will"
2086+
exit 1
2087+
;;
2088+
5222) # XMPP, see https://tools.ietf.org/html/rfc6120
2089+
starttls_just_read
2090+
[[ -z $XMPP_HOST ]] && XMPP_HOST="$NODE"
2091+
jabber=$(cat <<EOF
2092+
<?xml version='1.0' ?>
2093+
<stream:stream
2094+
xmlns:stream='http://etherx.jabber.org/streams'
2095+
xmlns='jabber:client'
2096+
to='$XMPP_HOST'
2097+
xml:lang='en'
2098+
version='1.0'>
2099+
EOF
2100+
)
2101+
starttls_line "$jabber"
2102+
starttls_line "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>" "proceed"
2103+
# BTW: https://xmpp.net !
2104+
;;
2105+
esac
2106+
fi
2107+
20112108
return 0
20122109
}
20132110

@@ -2017,13 +2114,9 @@ close_socket(){
20172114
exec 5>&-
20182115
return 0
20192116
}
2020-
## old network code ^^^^^^
2021-
20222117

2023-
###### new funcs for network follow
20242118

20252119
# first: helper function for protocol checks
2026-
20272120
code2network() {
20282121
# arg1: formatted string here in the code
20292122
NW_STR=$(echo "$1" | sed -e 's/,/\\\x/g' | sed -e 's/# .*$//g' -e 's/ //g' -e '/^$/d' | tr -d '\n' | tr -d '\t')
@@ -2050,9 +2143,8 @@ sockread_serverhello() {
20502143

20512144
SOCK_REPLY_FILE=$(mktemp $TEMPDIR/ddreply.XXXXXX) || return 7
20522145
dd bs=$1 of=$SOCK_REPLY_FILE count=1 <&5 2>/dev/null &
2053-
pid=$!
2146+
wait_kill $! $maxsleep
20542147

2055-
wait_kill $pid $maxsleep
20562148
return $?
20572149
}
20582150

@@ -2458,7 +2550,7 @@ heartbleed(){
24582550
[ $VULN_COUNT -le $VULN_THRESHLD ] && outln && pr_blue "--> Testing for heartbleed vulnerability" && outln "\n"
24592551
pr_bold " Heartbleed\c"; out " (CVE-2014-0160) "
24602552

2461-
if [ ! -z "$STARTTLS" ] ; then
2553+
if [[ -n "$STARTTLS" ]] && [[ $EXPERIMENTAL != "yes" ]] ; then
24622554
outln "(not yet implemented for STARTTLS)"
24632555
return 0
24642556
fi
@@ -2578,7 +2670,7 @@ ccs_injection(){
25782670
[ $VULN_COUNT -le $VULN_THRESHLD ] && outln && pr_blue "--> Testing for CCS injection vulnerability" && outln "\n"
25792671
pr_bold " CCS"; out " (CVE-2014-0224) "
25802672

2581-
if [ ! -z "$STARTTLS" ] ; then
2673+
if [[ -n "$STARTTLS" ]] && [[ $EXPERIMENTAL != "yes" ]] ; then
25822674
outln "(not yet implemented for STARTTLS)"
25832675
return 0
25842676
fi
@@ -2629,23 +2721,27 @@ ccs_injection(){
26292721

26302722
fd_socket 5 || return 6
26312723

2632-
[[ $DEBUG -ge 2 ]] && out "\nsending client hello, "
2724+
# we now make a standard handshake ...
2725+
debugme out "\nsending client hello, "
26332726
socksend "$client_hello" 1
26342727
sockread 16384
26352728

2636-
[[ $DEBUG -ge 2 ]] && outln "\nreading server hello"
2729+
debugme outln "\nreading server hello"
26372730
if [[ $DEBUG -ge 3 ]]; then
26382731
echo "$SOCKREPLY" | "${HEXDUMPVIEW[@]}" | head -20
26392732
outln "[...]"
26402733
outln "\npayload #1 with TLS version $tls_hexcode:"
26412734
fi
26422735

2736+
# ... and then send the a change cipher spec message
26432737
socksend "$ccs_message" 1 || ok_ids
26442738
sockread 2048 $CCS_MAX_WAITSOCK
26452739
if [[ $DEBUG -ge 3 ]]; then
26462740
outln "\n1st reply: "
26472741
out "$SOCKREPLY" | "${HEXDUMPVIEW[@]}" | head -20
2648-
# ok: 15 | 0301 | 02 | 02 0a == ALERT | TLS 1.0 | Length=2 | Unexpected Message (0a)
2742+
# ok: 15 | 0301 | 02 | 02 | 0a
2743+
# ALERT | TLS 1.0 | Length=2 | Unexpected Message (0a)
2744+
# or just timed out
26492745
outln
26502746
outln "payload #2 with TLS version $tls_hexcode:"
26512747
fi
@@ -2656,16 +2752,18 @@ ccs_injection(){
26562752

26572753
if [[ $DEBUG -ge 3 ]]; then
26582754
outln "\n2nd reply: "
2659-
out "$SOCKREPLY" | "${HEXDUMPVIEW[@]}"
2660-
# not ok: 15 | 0301 | 02 | 02 | 15 == ALERT | TLS 1.0 | Length=2 | Decryption failed (21)
2755+
printf -- "$SOCKREPLY" | "${HEXDUMPVIEW[@]}"
2756+
# not ok: 15 | 0301 | 02 | 02 | 15
2757+
# ALERT | TLS 1.0 | Length=2 | Decryption failed (21)
26612758
# ok: 0a or nothing: ==> RST
26622759
outln
26632760
fi
26642761

2665-
reply_sanitized=$(echo "$SOCKREPLY" | "${HEXDUMPPLAIN[@]}" | sed 's/^..........//')
2666-
lines=$(echo "$SOCKREPLY" | "${HEXDUMP[@]}" | wc -l | sed 's/ //g')
2762+
byte6=$(echo "$SOCKREPLY" | "${HEXDUMPPLAIN[@]}" | sed 's/^..........//')
2763+
lines=$(echo "$SOCKREPLY" | "${HEXDUMP[@]}" | count_lines )
2764+
debugme echo "lines: $lines, byte6: $byte6"
26672765

2668-
if [ "$reply_sanitized" == "0a" ] || [ "$lines" -gt 1 ] ; then
2766+
if [ "$byte6" == "0a" ] || [ "$lines" -gt 1 ] ; then
26692767
pr_green "not vulnerable (OK)"
26702768
ret=0
26712769
else
@@ -2856,8 +2954,7 @@ Connection: close
28562954
28572955
EOF
28582956
) &>$HEADERFILE_BREACH &
2859-
pid=$!
2860-
if wait_kill $pid $HEADER_MAXSLEEP; then
2957+
if wait_kill $! $HEADER_MAXSLEEP; then
28612958
result=$(grep -a '^Content-Encoding' $HEADERFILE_BREACH | sed -e 's/^Content-Encoding//' -e 's/://' -e 's/ //g')
28622959
result=$(echo $result | tr -cd '\40-\176')
28632960
if [ -z $result ]; then
@@ -4276,4 +4373,4 @@ fi
42764373
exit $ret
42774374

42784375

4279-
# $Id: testssl.sh,v 1.301 2015/07/06 18:42:42 dirkw Exp $
4376+
# $Id: testssl.sh,v 1.304 2015/07/07 20:59:30 dirkw Exp $

0 commit comments

Comments
 (0)