mirror of
https://github.com/drwetter/testssl.sh.git
synced 2025-01-03 23:39:45 +01:00
- FIX for date --> applied to other BSD systems too
- FIX for SNI output as it doensn';t make sense for non HTTP servives - lines for RC4 and PFS shortenedA - display all MX records to test before testing - removed LOCERR, added CCS_MAX_WAITSOCK, HEARTBLEED_MAX_WAITSOCK
This commit is contained in:
parent
f8ba69f9fb
commit
263535520f
85
testssl.sh
85
testssl.sh
@ -56,12 +56,13 @@ ASSUMING_HTTP=${ASSUMING_HTTP:-0} # in seldom cases (WAF, old servers/grumpy SS
|
|||||||
DEBUG=${DEBUG:-0} # if 1 the temp files won't be erased. 2: list more what's going on (formerly: eq VERBOSE=1),
|
DEBUG=${DEBUG:-0} # if 1 the temp files won't be erased. 2: list more what's going on (formerly: eq VERBOSE=1),
|
||||||
# 3: slight hexdumps and other info, 4: the whole nine yards of output
|
# 3: slight hexdumps and other info, 4: the whole nine yards of output
|
||||||
#FIXME: still to be filled with (more) sense or following to be included:
|
#FIXME: still to be filled with (more) sense or following to be included:
|
||||||
LOCERR=${LOCERR:-0} # displays the local error
|
VERBERR=${VERBERR:-1} # 0 means/to be more verbose (some like the errors to be dispayed so that one can tell better
|
||||||
VERBERR=${VERBERR:-1} # 0 means to be more verbose (some like the errors to be dispayed so that one can tell better
|
|
||||||
# whether handshake succeeded or not. For errors with individual ciphers you also need to have SHOW_EACH_C=1
|
# whether handshake succeeded or not. For errors with individual ciphers you also need to have SHOW_EACH_C=1
|
||||||
|
|
||||||
HEADER_MAXSLEEP=${HEADER_MAXSLEEP:-3} # we wait this long before killing the process to retrieve a service banner / http header
|
HEADER_MAXSLEEP=${HEADER_MAXSLEEP:-3} # we wait this long before killing the process to retrieve a service banner / http header
|
||||||
MAX_WAITSOCK=10 # waiting at max 10 seconds for socket reply
|
MAX_WAITSOCK=10 # waiting at max 10 seconds for socket reply
|
||||||
|
CCS_MAX_WAITSOCK=5 # for the two CCS payload (each)
|
||||||
|
HEARTBLEED_MAX_WAITSOCK=8 # for the heartbleed payload
|
||||||
USLEEP_SND=${USLEEP_SND:-0.1} # sleep time for general socket send
|
USLEEP_SND=${USLEEP_SND:-0.1} # sleep time for general socket send
|
||||||
USLEEP_REC=${USLEEP_REC:-0.2} # sleep time for general socket receive
|
USLEEP_REC=${USLEEP_REC:-0.2} # sleep time for general socket receive
|
||||||
|
|
||||||
@ -289,7 +290,7 @@ fi
|
|||||||
|
|
||||||
debugme() {
|
debugme() {
|
||||||
if [[ $DEBUG -ge 2 ]]; then
|
if [[ $DEBUG -ge 2 ]]; then
|
||||||
echo "$@"
|
#echo "$@"
|
||||||
"$@"
|
"$@"
|
||||||
else
|
else
|
||||||
:
|
:
|
||||||
@ -664,7 +665,7 @@ prettyprint_local() {
|
|||||||
listciphers() {
|
listciphers() {
|
||||||
$OPENSSL ciphers $1 &>$TMPFILE
|
$OPENSSL ciphers $1 &>$TMPFILE
|
||||||
ret=$?
|
ret=$?
|
||||||
[[ $LOCERR -eq 1 ]] && cat $TMPFILE
|
debugme cat $TMPFILE
|
||||||
|
|
||||||
tmpfile_handle $FUNCNAME.txt
|
tmpfile_handle $FUNCNAME.txt
|
||||||
return $ret
|
return $ret
|
||||||
@ -708,7 +709,6 @@ std_cipherlists() {
|
|||||||
pr_magentaln "Local problem: No $singlespaces configured in $OPENSSL"
|
pr_magentaln "Local problem: No $singlespaces configured in $OPENSSL"
|
||||||
fi
|
fi
|
||||||
# we need lf in those cases:
|
# we need lf in those cases:
|
||||||
[[ $LOCERR -eq 1 ]] && echo
|
|
||||||
[[ $DEBUG -ge 2 ]] && echo
|
[[ $DEBUG -ge 2 ]] && echo
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1025,6 +1025,7 @@ server_preference() {
|
|||||||
# proto-check b4!
|
# proto-check b4!
|
||||||
$OPENSSL s_client $STARTTLS -"$p" -connect $NODEIP:$PORT $SNI </dev/null 2>/dev/null >$TMPFILE
|
$OPENSSL s_client $STARTTLS -"$p" -connect $NODEIP:$PORT $SNI </dev/null 2>/dev/null >$TMPFILE
|
||||||
if [ $ret -eq 0 ]; then
|
if [ $ret -eq 0 ]; then
|
||||||
|
#FIXME: BSD output is not so fine
|
||||||
proto[i]=$(grep -w "Protocol" $TMPFILE | sed -e 's/^ \+Protocol \+://' -e 's/ //g')
|
proto[i]=$(grep -w "Protocol" $TMPFILE | sed -e 's/^ \+Protocol \+://' -e 's/ //g')
|
||||||
cipher[i]=$(grep -w "Cipher" $TMPFILE | egrep -vw "New|is" | sed -e 's/^ \+Cipher \+://' -e 's/ //g')
|
cipher[i]=$(grep -w "Cipher" $TMPFILE | egrep -vw "New|is" | sed -e 's/^ \+Cipher \+://' -e 's/ //g')
|
||||||
[[ ${cipher[i]} == "0000" ]] && cipher[i]="" # Hack!
|
[[ ${cipher[i]} == "0000" ]] && cipher[i]="" # Hack!
|
||||||
@ -1140,9 +1141,17 @@ server_defaults() {
|
|||||||
$OPENSSL x509 -noout -subject | sed 's/subject= //' | sed -e 's/^.*CN=//' -e 's/\/emailAdd.*//')
|
$OPENSSL x509 -noout -subject | sed 's/subject= //' | sed -e 's/^.*CN=//' -e 's/\/emailAdd.*//')
|
||||||
[[ $DEBUG -ge 2 ]] && out "$NODE | $CN | $CN_nosni"
|
[[ $DEBUG -ge 2 ]] && out "$NODE | $CN | $CN_nosni"
|
||||||
if [[ $NODE == $CN_nosni ]]; then
|
if [[ $NODE == $CN_nosni ]]; then
|
||||||
outln " (works w/o SNI)"
|
if [[ $SERVICE != "HTTP" ]] ; then
|
||||||
|
outln " (matches certificate directly)"
|
||||||
|
else
|
||||||
|
outln " (works w/o SNI)"
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
outln " (CN response to request w/o SNI: '$CN_nosni')"
|
if [[ $SERVICE != "HTTP" ]] ; then
|
||||||
|
pr_brownln " (CN doesn't match but for non-HTTP services it might be ok)"
|
||||||
|
else
|
||||||
|
outln " (CN response to request w/o SNI: '$CN_nosni')"
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
SAN=$($OPENSSL x509 -in $HOSTCERT -noout -text | grep -A3 "Subject Alternative Name" | grep "DNS:" | \
|
SAN=$($OPENSSL x509 -in $HOSTCERT -noout -text | grep -A3 "Subject Alternative Name" | grep "DNS:" | \
|
||||||
@ -1187,7 +1196,7 @@ server_defaults() {
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
case $(uname -s) in
|
case $(uname -s) in
|
||||||
FreeBSD|Mac*)
|
*BSD|Mac*)
|
||||||
enddate=$(date -j -f "%b %d %T %Y %Z" "$($OPENSSL x509 -in $HOSTCERT -noout -enddate | cut -d= -f 2)" +"%F %H:%M %z")
|
enddate=$(date -j -f "%b %d %T %Y %Z" "$($OPENSSL x509 -in $HOSTCERT -noout -enddate | cut -d= -f 2)" +"%F %H:%M %z")
|
||||||
startdate=$(date -j -f "%b %d %T %Y %Z" "$($OPENSSL x509 -in $HOSTCERT -noout -startdate | cut -d= -f 2)" +"%F %H:%M")
|
startdate=$(date -j -f "%b %d %T %Y %Z" "$($OPENSSL x509 -in $HOSTCERT -noout -startdate | cut -d= -f 2)" +"%F %H:%M")
|
||||||
;;
|
;;
|
||||||
@ -1257,7 +1266,7 @@ pfs() {
|
|||||||
local number_pfs
|
local number_pfs
|
||||||
local hexcode n ciph sslvers kx auth enc mac
|
local hexcode n ciph sslvers kx auth enc mac
|
||||||
local pfs_ciphers='EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA256 EECDH+aRSA+SHA256 EECDH+aRSA+RC4 EDH+aRSA EECDH RC4 !RC4-SHA !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS:@STRENGTH'
|
local pfs_ciphers='EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA256 EECDH+aRSA+SHA256 EECDH+aRSA+RC4 EDH+aRSA EECDH RC4 !RC4-SHA !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS:@STRENGTH'
|
||||||
# ^^^ the exclusing via ! doesn't work with libressl.
|
# ^^^ the exclusion via ! doesn't work with libressl.
|
||||||
# https://community.qualys.com/blogs/securitylabs/2013/08/05/configuring-apache-nginx-and-openssl-for-forward-secrecy
|
# https://community.qualys.com/blogs/securitylabs/2013/08/05/configuring-apache-nginx-and-openssl-for-forward-secrecy
|
||||||
|
|
||||||
# pfs_ciphers='EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH'
|
# pfs_ciphers='EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH'
|
||||||
@ -1284,10 +1293,10 @@ pfs() {
|
|||||||
ret=$?
|
ret=$?
|
||||||
outln
|
outln
|
||||||
if [ $ret -ne 0 ] || [ $(grep -c "BEGIN CERTIFICATE" $TMPFILE) -eq 0 ]; then
|
if [ $ret -ne 0 ] || [ $(grep -c "BEGIN CERTIFICATE" $TMPFILE) -eq 0 ]; then
|
||||||
pr_brown "No PFS available"
|
pr_brownln "Not OK: No ciphers supporting Forward Secrecy offered"
|
||||||
else
|
else
|
||||||
pr_litegreenln "In general PFS is offered. Now testing specific ciphers ...";
|
pr_litegreen "OK: PFS is offered. ";
|
||||||
outln "(it depends on the browser/client whether one of them will be used)\n"
|
outln "Client/browser support is important here. Offered PFS server ciphers follow... \n"
|
||||||
none=0
|
none=0
|
||||||
neat_header
|
neat_header
|
||||||
while read hexcode n ciph sslvers kx auth enc mac; do
|
while read hexcode n ciph sslvers kx auth enc mac; do
|
||||||
@ -1309,7 +1318,6 @@ pfs() {
|
|||||||
outln
|
outln
|
||||||
done < <($OPENSSL ciphers -V "$pfs_ciphers")
|
done < <($OPENSSL ciphers -V "$pfs_ciphers")
|
||||||
# ^^^^^ posix redirect as shopt will either segfault or doesn't work with old bash versions
|
# ^^^^^ posix redirect as shopt will either segfault or doesn't work with old bash versions
|
||||||
outln
|
|
||||||
debugme echo $none
|
debugme echo $none
|
||||||
|
|
||||||
if [ "$none" -eq 0 ] ; then
|
if [ "$none" -eq 0 ] ; then
|
||||||
@ -1319,6 +1327,8 @@ pfs() {
|
|||||||
ret=0
|
ret=0
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
outln
|
||||||
|
|
||||||
tmpfile_handle $FUNCNAME.txt
|
tmpfile_handle $FUNCNAME.txt
|
||||||
return $ret
|
return $ret
|
||||||
}
|
}
|
||||||
@ -1334,9 +1344,9 @@ rc4() {
|
|||||||
[ $SHOW_LOC_CIPH = "1" ] && echo "local ciphers available for testing RC4:" && echo $(cat $TMPFILE)
|
[ $SHOW_LOC_CIPH = "1" ] && echo "local ciphers available for testing RC4:" && echo $(cat $TMPFILE)
|
||||||
$OPENSSL s_client -cipher $($OPENSSL ciphers RC4) $STARTTLS -connect $NODEIP:$PORT $SNI &>/dev/null </dev/null
|
$OPENSSL s_client -cipher $($OPENSSL ciphers RC4) $STARTTLS -connect $NODEIP:$PORT $SNI &>/dev/null </dev/null
|
||||||
if [ $? -eq 0 ]; then
|
if [ $? -eq 0 ]; then
|
||||||
pr_literedln "\nRC4 is broken and is offered! Now testing specific ciphers...";
|
pr_litered "\nNOT ok: borken RC4 is being offered!"
|
||||||
outln "(for legacy support e.g. IE6 rather consider x13 or x0a)\n"
|
outln " Now testing specific ciphers...\n"
|
||||||
bad=1
|
rc4_offered=1
|
||||||
neat_header
|
neat_header
|
||||||
while read hexcode n ciph sslvers kx auth enc mac; do
|
while read hexcode n ciph sslvers kx auth enc mac; do
|
||||||
$OPENSSL s_client -cipher $ciph $STARTTLS -connect $NODEIP:$PORT $SNI </dev/null &>/dev/null
|
$OPENSSL s_client -cipher $ciph $STARTTLS -connect $NODEIP:$PORT $SNI </dev/null &>/dev/null
|
||||||
@ -1353,7 +1363,7 @@ rc4() {
|
|||||||
out "not a/v"
|
out "not a/v"
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
bad=1
|
rc4_offered=1
|
||||||
out
|
out
|
||||||
fi
|
fi
|
||||||
outln
|
outln
|
||||||
@ -1363,11 +1373,11 @@ rc4() {
|
|||||||
else
|
else
|
||||||
outln
|
outln
|
||||||
pr_litegreenln "no RC4 ciphers detected (OK)"
|
pr_litegreenln "no RC4 ciphers detected (OK)"
|
||||||
bad=0
|
rc4_offered=0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
tmpfile_handle $FUNCNAME.txt
|
tmpfile_handle $FUNCNAME.txt
|
||||||
return $bad
|
return $rc4_offered
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1410,7 +1420,7 @@ EOF
|
|||||||
pr_green "no HTTP compression (OK) "
|
pr_green "no HTTP compression (OK) "
|
||||||
ret=0
|
ret=0
|
||||||
else
|
else
|
||||||
pr_litered "NOT ok, uses $result compression "
|
pr_litered "NOT ok: uses $result compression "
|
||||||
ret=1
|
ret=1
|
||||||
fi
|
fi
|
||||||
# Catch: any URL can be vulnerable. I am testing now only the root. URL!
|
# Catch: any URL can be vulnerable. I am testing now only the root. URL!
|
||||||
@ -1926,7 +1936,7 @@ ccs_injection(){
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
socksend "$ccs_message" 1 || ok_ids
|
socksend "$ccs_message" 1 || ok_ids
|
||||||
sockread 2048 5 # 5 seconds
|
sockread 2048 $CCS_MAX_WAITSOCK
|
||||||
if [[ $DEBUG -ge 3 ]]; then
|
if [[ $DEBUG -ge 3 ]]; then
|
||||||
outln "\n1st reply: "
|
outln "\n1st reply: "
|
||||||
out "$SOCKREPLY" | "${HEXDUMPVIEW[@]}" | head -20
|
out "$SOCKREPLY" | "${HEXDUMPVIEW[@]}" | head -20
|
||||||
@ -1936,7 +1946,7 @@ ccs_injection(){
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
socksend "$ccs_message" 2 || ok_ids
|
socksend "$ccs_message" 2 || ok_ids
|
||||||
sockread 2048 5
|
sockread 2048 $CCS_MAX_WAITSOCK
|
||||||
retval=$?
|
retval=$?
|
||||||
|
|
||||||
if [[ $DEBUG -ge 3 ]]; then
|
if [[ $DEBUG -ge 3 ]]; then
|
||||||
@ -1954,7 +1964,7 @@ ccs_injection(){
|
|||||||
pr_green "not vulnerable (OK)"
|
pr_green "not vulnerable (OK)"
|
||||||
ret=0
|
ret=0
|
||||||
else
|
else
|
||||||
pr_red "VULNERABLE (not OK)"
|
pr_red "VULNERABLE (NOT ok)"
|
||||||
ret=1
|
ret=1
|
||||||
fi
|
fi
|
||||||
[ $retval -eq 3 ] && out "(timed out)"
|
[ $retval -eq 3 ] && out "(timed out)"
|
||||||
@ -2042,7 +2052,7 @@ heartbleed(){
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
socksend "$heartbleed_payload" 1
|
socksend "$heartbleed_payload" 1
|
||||||
sockread 16384
|
sockread 16384 $HEARTBLEED_MAX_WAITSOCK
|
||||||
retval=$?
|
retval=$?
|
||||||
|
|
||||||
if [[ $DEBUG -ge 3 ]]; then
|
if [[ $DEBUG -ge 3 ]]; then
|
||||||
@ -2543,19 +2553,22 @@ CAPATH: $CAPATH
|
|||||||
ECHO: $ECHO
|
ECHO: $ECHO
|
||||||
COLOR: $COLOR
|
COLOR: $COLOR
|
||||||
SHOW_LOC_CIPH: $SHOW_LOC_CIPH
|
SHOW_LOC_CIPH: $SHOW_LOC_CIPH
|
||||||
VERBERR: $VERBERR
|
SSL_NATIVE: $SSL_NATIVE
|
||||||
LOCERR: $LOCERR
|
ASSUMING_HTTP $ASSUMING_HTTP
|
||||||
SHOW_EACH_C: $SHOW_EACH_C
|
|
||||||
SNEAKY: $SNEAKY
|
SNEAKY: $SNEAKY
|
||||||
|
|
||||||
|
VERBERR: $VERBERR
|
||||||
|
SHOW_EACH_C: $SHOW_EACH_C
|
||||||
DEBUG: $DEBUG
|
DEBUG: $DEBUG
|
||||||
|
|
||||||
HSTS_MIN: $HSTS_MIN
|
HSTS_MIN: $HSTS_MIN
|
||||||
HPKP_MIN: $HPKP_MIN
|
HPKP_MIN: $HPKP_MIN
|
||||||
MAX_WAITSOCK: $MAX_WAITSOCK
|
MAX_WAITSOCK: $MAX_WAITSOCK
|
||||||
HEADER_MAXSLEEP: $HEADER_MAXSLEEP
|
CCS_MAX_WAITSOCK: $CCS_MAX_WAITSOCK
|
||||||
CLIENT_MIN_PFS: $CLIENT_MIN_PFS
|
HEARTBLEED_MAX_WAITSOCK: $HEARTBLEED_MAX_WAITSOCK
|
||||||
DAYS2WARN1: $DAYS2WARN1
|
|
||||||
DAYS2WARN2: $DAYS2WARN2
|
USLEEP_SND $USLEEP_SND
|
||||||
|
USLEEP_REC $USLEEP_REC
|
||||||
|
|
||||||
EOF
|
EOF
|
||||||
$OPENSSL ciphers -V $1 &>$TEMPDIR/all_local_ciphers.txt
|
$OPENSSL ciphers -V $1 &>$TEMPDIR/all_local_ciphers.txt
|
||||||
@ -2673,7 +2686,7 @@ parse_hn_port() {
|
|||||||
$OPENSSL s_client -connect "$NODE:$PORT" $SNI </dev/null >/dev/null 2>&1
|
$OPENSSL s_client -connect "$NODE:$PORT" $SNI </dev/null >/dev/null 2>&1
|
||||||
if [ $? -ne 0 ]; then
|
if [ $? -ne 0 ]; then
|
||||||
pr_boldln "$NODE:$PORT doesn't seem a TLS/SSL enabled server or it requires a certificate";
|
pr_boldln "$NODE:$PORT doesn't seem a TLS/SSL enabled server or it requires a certificate";
|
||||||
ignore_no_or_lame "Proceed (note that the results might look ok but they are nonsense) ? "
|
ignore_no_or_lame "Note that the results might look ok but they are nonsense. Proceed ? "
|
||||||
[ $? -ne 0 ] && exit 3
|
[ $? -ne 0 ] && exit 3
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
@ -2681,6 +2694,7 @@ parse_hn_port() {
|
|||||||
datebanner "Testing"
|
datebanner "Testing"
|
||||||
[[ -z "$2" ]] && runs_HTTP # for starttls we don't check the protocol as it is supplied on the cmd line
|
[[ -z "$2" ]] && runs_HTTP # for starttls we don't check the protocol as it is supplied on the cmd line
|
||||||
initialize_engine
|
initialize_engine
|
||||||
|
outln
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
@ -2782,9 +2796,10 @@ mx_allentries() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# test first higher priority servers
|
# test first higher priority servers
|
||||||
MXs=$(echo "$MXs" | sort -n | sed -e 's/^.* //' -e 's/\.$//')
|
MXs=$(echo "$MXs" | sort -n | sed -e 's/^.* //' -e 's/\.$//' | tr '\n' ' ')
|
||||||
|
|
||||||
if [ -n "$MXs" ] ; then
|
if [ -n "$MXs" ] ; then
|
||||||
|
pr_bold "Testing now all MX records (on port 25): "; outln "$MXs"
|
||||||
for MX in $MXs; do
|
for MX in $MXs; do
|
||||||
parse_hn_port "$MX:25" 'smtp' && starttls 'smtp'
|
parse_hn_port "$MX:25" 'smtp' && starttls 'smtp'
|
||||||
done
|
done
|
||||||
@ -2999,6 +3014,6 @@ case "$1" in
|
|||||||
exit $ret ;;
|
exit $ret ;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
# $Id: testssl.sh,v 1.209 2015/03/15 23:22:50 dirkw Exp $
|
# $Id: testssl.sh,v 1.210 2015/03/17 11:22:20 dirkw Exp $
|
||||||
# vim:ts=5:sw=5
|
# vim:ts=5:sw=5
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user