mirror of
https://github.com/drwetter/testssl.sh.git
synced 2025-01-03 23:39:45 +01:00
* NEW: protocol check SSLv2 in bash sockets per default (HTTP)
(fallback to openssl with SSL_NATIVE=1)
This commit is contained in:
parent
b2e8e0175a
commit
89012a7a42
207
testssl.sh
207
testssl.sh
@ -44,8 +44,6 @@ SWCONTACT="dirk aet testssl dot sh"
|
|||||||
|
|
||||||
|
|
||||||
# following variables make use of $ENV, e.g. OPENSSL=<myprivate_path_to_openssl> ./testssl.sh <host>
|
# following variables make use of $ENV, e.g. OPENSSL=<myprivate_path_to_openssl> ./testssl.sh <host>
|
||||||
CAPATH="${CAPATH:-/etc/ssl/certs/}" # Does nothing yet. FC has only a CA bundle per default, ==> openssl version -d
|
|
||||||
ECHO="/usr/bin/printf --" # works under Linux, BSD, MacOS.
|
|
||||||
COLOR=${COLOR:-2} # 2: Full color, 1: b/w+positioning, 0: no ESC at all
|
COLOR=${COLOR:-2} # 2: Full color, 1: b/w+positioning, 0: no ESC at all
|
||||||
SHOW_LOC_CIPH=${SHOW_LOC_CIPH:-0} # determines whether the client side ciphers are displayed at all (makes no sense normally)
|
SHOW_LOC_CIPH=${SHOW_LOC_CIPH:-0} # determines whether the client side ciphers are displayed at all (makes no sense normally)
|
||||||
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
|
||||||
@ -53,11 +51,15 @@ VERBERR=${VERBERR:-1} # 0 means to be more verbose (some like the errors to b
|
|||||||
LOCERR=${LOCERR:-0} # displays the local error
|
LOCERR=${LOCERR:-0} # displays the local error
|
||||||
SHOW_EACH_C=${SHOW_EACH_C:-0} # where individual ciphers are tested show just the positively ones tested
|
SHOW_EACH_C=${SHOW_EACH_C:-0} # where individual ciphers are tested show just the positively ones tested
|
||||||
SNEAKY=${SNEAKY:-1} # if zero: the referer and useragent we leave while checking the http header is just usual
|
SNEAKY=${SNEAKY:-1} # if zero: the referer and useragent we leave while checking the http header is just usual
|
||||||
|
HEADER_MAXSLEEP=${HEADER_MAXSLEEP:-3} # we wait this long before killing the process to retrieve a service banner / http header
|
||||||
|
SSL_NATIVE=${SSL_NATIVE:-0} # we do per default bash sockets!
|
||||||
#FIXME: consequently we should mute the initial openssl s_client -connect as they cause a 400 (nginx, apache)
|
#FIXME: consequently we should mute the initial openssl s_client -connect as they cause a 400 (nginx, apache)
|
||||||
|
|
||||||
#FIXME: still to be filled with (more) sense:
|
#FIXME: still to be filled with (more) sense:
|
||||||
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
|
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
|
# and other info, 4: the whole nine yards of output
|
||||||
|
|
||||||
|
CAPATH="${CAPATH:-/etc/ssl/certs/}" # Does nothing yet. FC has only a CA bundle per default, ==> openssl version -d
|
||||||
HSTS_MIN=180 # >180 days is ok for HSTS
|
HSTS_MIN=180 # >180 days is ok for HSTS
|
||||||
HPKP_MIN=30 # >=30 days should be ok for HPKP_MIN, practical hints?
|
HPKP_MIN=30 # >=30 days should be ok for HPKP_MIN, practical hints?
|
||||||
MAX_WAITSOCK=10 # waiting at max 10 seconds for socket reply
|
MAX_WAITSOCK=10 # waiting at max 10 seconds for socket reply
|
||||||
@ -66,6 +68,9 @@ DAYS2WARN1=60 # days to warn before cert expires, threshold 1
|
|||||||
DAYS2WARN2=30 # days to warn before cert expires, threshold 2
|
DAYS2WARN2=30 # days to warn before cert expires, threshold 2
|
||||||
|
|
||||||
# more global vars, here just declared
|
# more global vars, here just declared
|
||||||
|
ECHO="/usr/bin/printf --" # works under Linux, BSD, MacOS.
|
||||||
|
NPN_PROTOs="spdy/4a2,spdy/3,spdy/3.1,spdy/2,spdy/1,http/1.1"
|
||||||
|
RUN_DIR=`dirname $0`
|
||||||
TEMPDIR=""
|
TEMPDIR=""
|
||||||
TLS_PROTO_OFFERED=""
|
TLS_PROTO_OFFERED=""
|
||||||
SOCKREPLY=""
|
SOCKREPLY=""
|
||||||
@ -80,10 +85,7 @@ OSSL_VER_APPENDIX="none"
|
|||||||
NODEIP=""
|
NODEIP=""
|
||||||
IPS=""
|
IPS=""
|
||||||
SERVICE="" # is the server running an HTTP server, SMTP, POP or IMAP?
|
SERVICE="" # is the server running an HTTP server, SMTP, POP or IMAP?
|
||||||
HEADER_MAXSLEEP=${HEADER_MAXSLEEP:-3} # we wait this long before killing the process to retrieve a service banner / http header
|
|
||||||
|
|
||||||
NPN_PROTOs="spdy/4a2,spdy/3,spdy/3.1,spdy/2,spdy/1,http/1.1"
|
|
||||||
RUN_DIR=`dirname $0`
|
|
||||||
BLA=""
|
BLA=""
|
||||||
|
|
||||||
|
|
||||||
@ -188,7 +190,7 @@ pr_brown() {
|
|||||||
pr_off
|
pr_off
|
||||||
}
|
}
|
||||||
|
|
||||||
pr_yellowln() { pr_yellowln "$1"; outln; }
|
pr_yellowln() { pr_yellow "$1"; outln; }
|
||||||
pr_yellow() {
|
pr_yellow() {
|
||||||
[[ "$COLOR" -eq 2 ]] && out "\033[1;33m$1 " || out "$1 "
|
[[ "$COLOR" -eq 2 ]] && out "\033[1;33m$1 " || out "$1 "
|
||||||
pr_off
|
pr_off
|
||||||
@ -238,7 +240,7 @@ ok(){
|
|||||||
case $1 in
|
case $1 in
|
||||||
7) pr_brownln "not offered" ;; # 7 0
|
7) pr_brownln "not offered" ;; # 7 0
|
||||||
6) pr_literedln "offered (NOT ok)" ;; # 6 0
|
6) pr_literedln "offered (NOT ok)" ;; # 6 0
|
||||||
5) pr_litered "supported but couldn't detect a cipher"; outln "(check manually)" ;; # 5 5
|
5) pr_litered "supported but couldn't detect a cipher"; outln "(may need debugging)" ;; # 5 5
|
||||||
4) pr_litegreenln "offered (OK)" ;; # 4 0
|
4) pr_litegreenln "offered (OK)" ;; # 4 0
|
||||||
3) pr_brownln "offered" ;; # 3 0
|
3) pr_brownln "offered" ;; # 3 0
|
||||||
2) outln "offered" ;; # 2 0
|
2) outln "offered" ;; # 2 0
|
||||||
@ -849,13 +851,17 @@ runprotocols() {
|
|||||||
pr_blue "--> Testing Protocols"; outln "\n"
|
pr_blue "--> Testing Protocols"; outln "\n"
|
||||||
# e.g. ubuntu's 12.04 openssl binary + soon others don't want sslv2 anymore: bugs.launchpad.net/ubuntu/+source/openssl/+bug/955675
|
# e.g. ubuntu's 12.04 openssl binary + soon others don't want sslv2 anymore: bugs.launchpad.net/ubuntu/+source/openssl/+bug/955675
|
||||||
|
|
||||||
testprotohelper "-ssl2" " SSLv2 "
|
if [ $SSL_NATIVE -eq 1 ] || [ "$SERVICE" != "HTTP" ]; then
|
||||||
case $? in
|
testprotohelper "-ssl2" " SSLv2 "
|
||||||
0) ok 1 1 ;; # pr_red
|
case $? in
|
||||||
5) ok 5 5 ;; # protocol ok, but no cipher
|
0) ok 1 1 ;; # pr_red
|
||||||
1) ok 0 1 ;; # pr_green "not offered (ok)"
|
5) ok 5 5 ;; # protocol ok, but no cipher
|
||||||
7) ;; # no local support
|
1) ok 0 1 ;; # pr_green "not offered (ok)"
|
||||||
esac
|
7) ;; # no local support
|
||||||
|
esac
|
||||||
|
else
|
||||||
|
sslv2_sockets
|
||||||
|
fi
|
||||||
|
|
||||||
testprotohelper "-ssl3" " SSLv3 "
|
testprotohelper "-ssl3" " SSLv3 "
|
||||||
case $? in
|
case $? in
|
||||||
@ -963,7 +969,7 @@ server_preference() {
|
|||||||
*CBC*) pr_brown "$default_cipher" ;; #FIXME BEAST: We miss some CBC ciphers here, need to work w/ a list
|
*CBC*) pr_brown "$default_cipher" ;; #FIXME BEAST: We miss some CBC ciphers here, need to work w/ a list
|
||||||
*GCM*) pr_green "$default_cipher" ;; # best ones
|
*GCM*) pr_green "$default_cipher" ;; # best ones
|
||||||
*CHACHA20*) pr_green "$default_cipher" ;; # best ones
|
*CHACHA20*) pr_green "$default_cipher" ;; # best ones
|
||||||
ECDHE*AES*) pr_yellow "$default_cipher" ;; # it's CBC. so lucky13
|
ECDHE*AES*) pr_yellow "$default_cipher" ;; # it's CBC. --> lucky13
|
||||||
*) out "$default_cipher" ;;
|
*) out "$default_cipher" ;;
|
||||||
esac
|
esac
|
||||||
outln "$remark4default_cipher"
|
outln "$remark4default_cipher"
|
||||||
@ -1210,7 +1216,7 @@ pfs() {
|
|||||||
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_brown "No PFS available"
|
||||||
else
|
else
|
||||||
pr_litegreenln "PFS seems generally available. Now testing specific ciphers ...";
|
pr_litegreenln "PFS is generally offered. Now testing specific ciphers ...";
|
||||||
outln "(it depends on the browser/client whether one of them will be used)\n"
|
outln "(it depends on the browser/client whether one of them will be used)\n"
|
||||||
noone=0
|
noone=0
|
||||||
neat_header
|
neat_header
|
||||||
@ -1255,7 +1261,7 @@ 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. It seems generally available. Now testing specific ciphers...";
|
pr_literedln "\nRC4 is broken and is offered! Now testing specific ciphers...";
|
||||||
outln "(for legacy support e.g. IE6 rather consider x13 or x0a)\n"
|
outln "(for legacy support e.g. IE6 rather consider x13 or x0a)\n"
|
||||||
bad=1
|
bad=1
|
||||||
neat_header
|
neat_header
|
||||||
@ -1370,10 +1376,164 @@ close_socket(){
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
## old network code ^^^^^^
|
||||||
|
|
||||||
|
|
||||||
|
### new funcs for network follow
|
||||||
|
|
||||||
|
socksend_clienthello() {
|
||||||
|
code2network "$SSLv2_CLIENT_HELLO"
|
||||||
|
data=`echo $NW_STR`
|
||||||
|
[[ "$DEBUG" -ge 3 ]] && echo "\"$data\""
|
||||||
|
printf -- "$data" >&5 2>/dev/null &
|
||||||
|
sleep $USLEEP_SND
|
||||||
|
}
|
||||||
|
|
||||||
|
sockread_serverhello() {
|
||||||
|
[[ "x$2" = "x" ]] && maxsleep=$MAX_WAITSOCK || maxsleep=$2
|
||||||
|
ret=0
|
||||||
|
|
||||||
|
SOCK_REPLY_FILE=`mktemp /tmp/ddreply.XXXXXX` || exit 7
|
||||||
|
dd bs=$1 of=$SOCK_REPLY_FILE count=1 <&5 2>/dev/null &
|
||||||
|
pid=$!
|
||||||
|
|
||||||
|
while true; do
|
||||||
|
if ! ps ax | grep -v grep | grep -q $pid; then
|
||||||
|
break # didn't reach maxsleep yet
|
||||||
|
kill $pid >&2 2>/dev/null
|
||||||
|
fi
|
||||||
|
sleep $USLEEP_REC
|
||||||
|
maxsleep=$(($maxsleep - 1))
|
||||||
|
[[ $maxsleep -le 0 ]] && break
|
||||||
|
done
|
||||||
|
|
||||||
|
if ps ax | grep -v grep | grep -q $pid; then
|
||||||
|
# time's up and dd is still alive --> timeout
|
||||||
|
kill $pid >&2 2>/dev/null
|
||||||
|
wait $pid 2>/dev/null
|
||||||
|
ret=3 # means killed
|
||||||
|
fi
|
||||||
|
|
||||||
|
return $ret
|
||||||
|
}
|
||||||
|
|
||||||
|
display_sslv2serverhello() {
|
||||||
|
# server hello: in hex representation, see below
|
||||||
|
# byte 1+2: length of server hello 0123
|
||||||
|
# 3: 04=Handshake message, server hello 45
|
||||||
|
# 4: session id hit or not (boolean: 00=false, this 67
|
||||||
|
# is the normal case)
|
||||||
|
# 5: certificate type, 01 = x509 89
|
||||||
|
# 6+7 version (00 02 = SSLv2) 10-13
|
||||||
|
# 8+9 certificate length 14-17
|
||||||
|
# 10+11 cipher spec length 17-20
|
||||||
|
# 12+13 connection id length
|
||||||
|
# [certificate length] ==> certificate
|
||||||
|
# [cipher spec length] ==> ciphers GOOD: HERE ARE ALL CIPHERS ALREADY!
|
||||||
|
|
||||||
|
v2_hello_ascii=`hexdump -v -e '16/1 "%02X"' $1`
|
||||||
|
[[ "$DEBUG" -ge 4 ]] && echo $v2_hello_ascii # one line without any blanks
|
||||||
|
[[ -z $v2_hello_ascii ]] && return 0 # no server hello received
|
||||||
|
|
||||||
|
# now scrape two bytes out of the reply per byte
|
||||||
|
v2_hello_initbyte="${v2_hello_ascii:0:1}" # normally this belongs to the next, should be 8!
|
||||||
|
v2_hello_length="${v2_hello_ascii:1:3}" # + 0x8000 see above
|
||||||
|
v2_hello_handshake="${v2_hello_ascii:4:2}"
|
||||||
|
v2_hello_cert_length="${v2_hello_ascii:14:4}"
|
||||||
|
v2_hello_cipherspec_length="${v2_hello_ascii:18:4}"
|
||||||
|
V2_HELLO_CIPHERSPEC_LENGTH=`printf "%d\n" "0x$v2_hello_cipherspec_length"`
|
||||||
|
|
||||||
|
if [[ $v2_hello_initbyte != "8" ]] || [[ $v2_hello_handshake != "04" ]]; then
|
||||||
|
[[ $DEBUG -ge 2 ]] && echo "$v2_hello_initbyte / $v2_hello_handshake"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ $DEBUG -ge 3 ]]; then
|
||||||
|
echo "SSLv2 server hello length: 0x0$v2_hello_length"
|
||||||
|
echo "SSLv2 certificate length: 0x$v2_hello_cert_length"
|
||||||
|
echo "SSLv2 cipher spec length: 0x$v2_hello_cipherspec_length"
|
||||||
|
fi
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# helper function for protocol checks
|
||||||
|
# arg1: formatted string here in the code
|
||||||
|
code2network() {
|
||||||
|
NW_STR=`echo "$1" | sed -e 's/,/\\\x/g' | sed -e 's/# .*$//g' -e 's/ //g' -e '/^$/d' | tr -d '\n' | tr -d '\t'`
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
sslv2_sockets() {
|
||||||
|
V2_HELLO_CIPHERSPEC_LENGTH=0 # initialize
|
||||||
|
USLEEP_REC=${USLEEP_REC:-0.2}
|
||||||
|
USLEEP_SND=${USLEEP_SND:-0.1} # 1 second wait until otherwise specified
|
||||||
|
SOCK_REPLY_FILE="" # we do this with a file here. At a certain point heartbleed and ccs needs to be changed and make use of code2network
|
||||||
|
NW_STR=""
|
||||||
|
|
||||||
|
out " SSLv2 ";
|
||||||
|
|
||||||
|
# SSLV2 chello:
|
||||||
|
SSLv2_CLIENT_HELLO="
|
||||||
|
,80,34 # length (here: 52)
|
||||||
|
,01 # Client Hello
|
||||||
|
,00,02 # SSLv2
|
||||||
|
,00,1b # cipher spec length (here: 27 )
|
||||||
|
,00,00 # session ID length
|
||||||
|
,00,10 # challenge length
|
||||||
|
,05,00,80 # 1st cipher 9 cipher specs, only classical V2 ciphers are used here, see http://max.euston.net/d/tip_sslciphers.html
|
||||||
|
,03,00,80 # 2nd there are v3 in v2!!! : https://tools.ietf.org/html/rfc6101#appendix-E
|
||||||
|
,01,00,80 # 3rd Cipher specifications introduced in version 3.0 can be included in version 2.0 client hello messages using
|
||||||
|
,07,00,c0 # 4th the syntax below. [..] # V2CipherSpec (see Version 3.0 name) = { 0x00, CipherSuite }; !!!!
|
||||||
|
,08,00,80 # 5th
|
||||||
|
,06,00,40 # 6th
|
||||||
|
,04,00,80 # 7th
|
||||||
|
,02,00,80 # 8th
|
||||||
|
,00,00,00 # 9th
|
||||||
|
,29,22,be,b3,5a,01,8b,04,fe,5f,80,03,a0,13,eb,c4" # Challenge
|
||||||
|
|
||||||
|
fd_socket 5 || return 6
|
||||||
|
|
||||||
|
[[ "$DEBUG" -ge 2 ]] && out "sending client hello... "
|
||||||
|
socksend_clienthello
|
||||||
|
|
||||||
|
sockread_serverhello 32768 0
|
||||||
|
[[ "$DEBUG" -ge 2 ]] && out "reading server hello... "
|
||||||
|
if [[ "$DEBUG" -eq 3 ]]; then
|
||||||
|
hexdump -C $SOCK_REPLY_FILE | head -6
|
||||||
|
outln
|
||||||
|
fi
|
||||||
|
|
||||||
|
display_sslv2serverhello "$SOCK_REPLY_FILE"
|
||||||
|
|
||||||
|
# see https://secure.wand.net.nz/trac/libprotoident/wiki/SSL
|
||||||
|
lines=`cat "$SOCK_REPLY_FILE" 2>/dev/null | hexdump -C | wc -l`
|
||||||
|
[[ "$DEBUG" -ge 2 ]] && out " ($lines lines) "
|
||||||
|
|
||||||
|
if [[ "$lines" -gt 1 ]] ;then
|
||||||
|
ciphers_detected=$(($V2_HELLO_CIPHERSPEC_LENGTH / 3 ))
|
||||||
|
if [ 0 -eq $ciphers_detected ] ; then
|
||||||
|
pr_litered "supported but couldn't detect a cipher"; outln "(may need debugging)"
|
||||||
|
else
|
||||||
|
pr_red "offered (NOT ok)"; outln " -- $ciphers_detected ciphers"
|
||||||
|
fi
|
||||||
|
ret=1
|
||||||
|
else
|
||||||
|
pr_greenln "not offered (OK)"
|
||||||
|
ret=0
|
||||||
|
fi
|
||||||
|
pr_off
|
||||||
|
|
||||||
|
close_socket
|
||||||
|
TMPFILE=$SOCK_REPLY_FILE
|
||||||
|
tmpfile_handle $FUNCNAME.dd
|
||||||
|
return $ret
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ok_ids(){
|
ok_ids(){
|
||||||
echo
|
greenln "\n ok -- something resetted our ccs packets"
|
||||||
tput pr_bold; tput setaf 2; echo "ok -- something resetted our ccs packets"; tput sgr0
|
|
||||||
echo
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1465,7 +1625,7 @@ ccs_injection(){
|
|||||||
|
|
||||||
if [ "$reply_sanitized" == "0a" ] || [ "$lines" -gt 1 ] ; then
|
if [ "$reply_sanitized" == "0a" ] || [ "$lines" -gt 1 ] ; then
|
||||||
pr_green "not vulnerable (OK)"
|
pr_green "not vulnerable (OK)"
|
||||||
ret=1
|
ret=0
|
||||||
else
|
else
|
||||||
pr_red "VULNERABLE"
|
pr_red "VULNERABLE"
|
||||||
ret=1
|
ret=1
|
||||||
@ -1714,11 +1874,10 @@ beast(){
|
|||||||
local -i ret=0
|
local -i ret=0
|
||||||
local spaces=" "
|
local spaces=" "
|
||||||
#in a nutshell: don't use CBC Ciphers in SSLv3 TLSv1.0
|
#in a nutshell: don't use CBC Ciphers in SSLv3 TLSv1.0
|
||||||
#
|
|
||||||
pr_bold " BEAST"; out " (CVE-2011-3389) "
|
pr_bold " BEAST"; out " (CVE-2011-3389) "
|
||||||
|
|
||||||
# 2) test handfull of common CBC ciphers
|
# 2) test handfull of common CBC ciphers
|
||||||
#set -x
|
|
||||||
for proto in ssl3 tls1; do
|
for proto in ssl3 tls1; do
|
||||||
$OPENSSL s_client -"$proto" $STARTTLS -connect $NODEIP:$PORT $SNI >$TMPFILE 2>/dev/null </dev/null
|
$OPENSSL s_client -"$proto" $STARTTLS -connect $NODEIP:$PORT $SNI >$TMPFILE 2>/dev/null </dev/null
|
||||||
if [ $? -ne 0 ]; then
|
if [ $? -ne 0 ]; then
|
||||||
@ -2389,6 +2548,6 @@ case "$1" in
|
|||||||
exit $ret ;;
|
exit $ret ;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
# $Id: testssl.sh,v 1.174 2015/01/29 08:33:33 dirkw Exp $
|
# $Id: testssl.sh,v 1.175 2015/01/29 09:46:15 dirkw Exp $
|
||||||
# vim:ts=5:sw=5
|
# vim:ts=5:sw=5
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user