2014-07-16 19:04:15 +02:00
#!/usr/bin/env bash
2014-12-08 10:32:51 +01:00
#
2014-10-29 21:24:43 +01:00
# bash is needed for some distros which use dash as /bin/sh and for tcp sockets which
2014-11-30 01:30:20 +01:00
# this program uses a couple of times. Also some expressions are bashisms as I expect
2015-01-30 16:26:55 +01:00
# them to be faster. Idea is to not overdo it though.
2014-07-01 16:28:16 +02:00
2014-12-08 10:32:51 +01:00
# testssl.sh is a program for spotting weak SSL encryption, ciphers, version and some
# vulnerablities or features
#
# Devel version is availabe from https://github.com/drwetter/testssl.sh,
# stable version from https://testssl.sh
2014-07-01 16:28:16 +02:00
2014-12-18 09:33:24 +01:00
VERSION = "2.3dev" # any char suffixes denotes non=stable
2014-07-01 16:28:16 +02:00
SWURL = "https://testssl.sh"
SWCONTACT = "dirk aet testssl dot sh"
2015-01-14 09:48:44 +01:00
# Author: Dirk Wetter, copyleft: 2007-2015, contributions so far see CREDIT.md
2014-07-01 16:28:16 +02:00
#
# License: GPLv2, see http://www.fsf.org/licensing/licenses/info/GPLv2.html
# and accompanying license "LICENSE.txt". Redistribution + modification under this
# license permitted.
# If you enclose this script or parts of it in your software, it has to
# be accompanied by the same license (see link) and the place where to get
2014-11-30 01:30:20 +01:00
# the recent version of this program. Don't violate the license!
2014-07-01 16:28:16 +02:00
#
# USAGE WITHOUT ANY WARRANTY, THE SOFTWARE IS PROVIDED "AS IS". USE IT AT
# your OWN RISK
2014-11-30 01:30:20 +01:00
# HISTORY: I know reading this shell script is sometimes neither nice nor is it rocket science
2015-01-30 16:26:55 +01:00
# (well ok, maybe the bash sockets are kind of cool).
# It all started with a few openssl commands. It is a such a good swiss army knife (see e.g.
# wiki.openssl.org/index.php/Command_Line_Utilities) that it was difficult to resist wrapping
# with some shell commandos around it. This is how everything started
# Probably you can achieve the same result with my favorite zsh (zmodload zsh/net/socket b4
# -- checkout zsh/net/tcp too! -- but bash is way more often used, within Linux and: cross-platform!
2014-07-01 16:28:16 +02:00
# Q: So what's the difference between https://www.ssllabs.com/ssltest or
# https://sslcheck.globalsign.com/?
2014-07-16 19:04:15 +02:00
# A: As of now ssllabs only check webservers on standard ports, reachable from
2015-01-30 16:26:55 +01:00
# the internet. And the examples above are 3rd parties. If those restrictions are fine
2014-07-01 16:28:16 +02:00
# with you, they might tell you more than this tool -- as of now.
2014-12-08 10:32:51 +01:00
# Note that for "standard" openssl binaries a lot of features (ciphers, protocols, vulnerabilities)
# are disabled as they'll impact security otherwise. For security testing though we
# need all those features. Thus it's highly recommended to use the suppied binaries.
# Except on-available local ciphers you'll get a warning about missing features
2014-07-01 16:28:16 +02:00
# following variables make use of $ENV, e.g. OPENSSL=<myprivate_path_to_openssl> ./testssl.sh <host>
2014-11-30 01:30:20 +01:00
COLOR = ${ COLOR :- 2 } # 2: Full color, 1: b/w+positioning, 0: no ESC at all
2015-01-21 12:53:00 +01:00
SHOW_LOC_CIPH = ${ SHOW_LOC_CIPH :- 0 } # determines whether the client side ciphers are displayed at all (makes no sense normally)
2014-11-30 01:30:20 +01:00
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
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
SNEAKY = ${ SNEAKY :- 1 } # if zero: the referer and useragent we leave while checking the http header is just usual
2015-01-29 10:46:16 +01:00
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!
2015-02-13 16:01:46 +01:00
ASSUMING_HTTP = ${ ASSUMING_HTTP :- 0 } # in seldom cases (WAF, old servers/grumpy SSL) the service detection fails. Set to 1 for HTTP
2014-07-01 16:28:16 +02:00
#FIXME: still to be filled with (more) sense:
2015-01-21 12:53:00 +01:00
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
2015-02-11 09:43:04 +01:00
PS4 = '+(${BASH_SOURCE}:${LINENO}): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'
2015-01-29 10:46:16 +01:00
CAPATH = " ${ CAPATH :- /etc/ssl/certs/ } " # Does nothing yet. FC has only a CA bundle per default, ==> openssl version -d
2014-11-27 21:33:33 +01:00
HSTS_MIN = 180 # >180 days is ok for HSTS
2014-12-08 10:32:51 +01:00
HPKP_MIN = 30 # >=30 days should be ok for HPKP_MIN, practical hints?
2014-11-30 01:30:20 +01:00
MAX_WAITSOCK = 10 # waiting at max 10 seconds for socket reply
2014-11-19 17:08:59 +01:00
CLIENT_MIN_PFS = 5 # number of ciphers needed to run a test for PFS
2014-12-18 09:33:24 +01:00
DAYS2WARN1 = 60 # days to warn before cert expires, threshold 1
DAYS2WARN2 = 30 # days to warn before cert expires, threshold 2
2014-07-01 16:28:16 +02:00
2015-01-21 12:53:00 +01:00
# more global vars, here just declared
2015-01-29 10:46:16 +01:00
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 `
2015-01-21 12:53:00 +01:00
TEMPDIR = ""
2014-07-01 16:28:16 +02:00
TLS_PROTO_OFFERED = ""
SOCKREPLY = ""
HEXC = ""
SNI = ""
IP4 = ""
IP6 = ""
2014-11-27 21:33:33 +01:00
OSSL_VER = "" # openssl version, will be autodetermined
2014-07-01 16:28:16 +02:00
OSSL_VER_MAJOR = 0
OSSL_VER_MINOR = 0
OSSL_VER_APPENDIX = "none"
NODEIP = ""
IPS = ""
2014-11-30 01:30:20 +01:00
SERVICE = "" # is the server running an HTTP server, SMTP, POP or IMAP?
2014-10-30 21:12:18 +01:00
2015-01-20 21:59:21 +01:00
BLA = ""
2014-11-27 21:33:33 +01:00
2014-11-18 04:30:48 +01:00
# make sure that temporary files are cleaned up after use
2015-01-20 21:59:21 +01:00
trap "cleanup" QUIT EXIT
2014-07-01 16:28:16 +02:00
2014-11-19 13:22:22 +01:00
# The various hexdump commands we need to replace xxd (BSD compatability))
HEXDUMPVIEW = ( hexdump -C) # This is used in verbose mode to see what's going on
HEXDUMP = ( hexdump -ve '16/1 "%02x " " \n"' ) # This is used to analyse the reply
HEXDUMPPLAIN = ( hexdump -ve '1/1 "%.2x"' ) # Replaces both xxd -p and tr -cd '[:print:]'
2015-01-29 09:33:35 +01:00
out( ) {
$ECHO " $1 "
2014-07-16 19:04:15 +02:00
}
2015-01-29 09:33:35 +01:00
outln( ) {
2014-11-27 21:33:33 +01:00
[ [ -z " $1 " ] ] || $ECHO " $1 "
2014-07-16 19:04:15 +02:00
$ECHO "\n"
}
2014-07-01 16:28:16 +02:00
# http://www.tldp.org/HOWTO/Bash-Prompt-HOWTO/x329.html
2015-01-29 09:33:35 +01:00
#### color print functions
2014-07-01 16:28:16 +02:00
2015-01-29 09:33:35 +01:00
pr_off( ) {
[ [ " $COLOR " -ne 0 ] ] && out "\033[m\c"
2014-07-01 16:28:16 +02:00
}
2014-07-16 19:04:15 +02:00
2015-01-29 09:33:35 +01:00
pr_liteblueln( ) { pr_liteblue " $1 " ; outln; }
pr_liteblue( ) {
[ [ " $COLOR " -eq 2 ] ] && out " \033[0;34m $1 " || out " $1 "
pr_off
2014-07-01 16:28:16 +02:00
}
2014-07-16 19:04:15 +02:00
2015-01-29 09:33:35 +01:00
pr_blueln( ) { pr_blue " $1 " ; outln; }
pr_blue( ) {
[ [ " $COLOR " -eq 2 ] ] && out " \033[1;34m $1 " || out " $1 "
pr_off
2014-07-01 16:28:16 +02:00
}
2014-07-16 19:04:15 +02:00
2015-01-29 09:33:35 +01:00
pr_literedln( ) { pr_litered " $1 " ; outln; }
pr_litered( ) {
[ [ " $COLOR " -eq 2 ] ] && out " \033[0;31m $1 " || pr_bold " $1 "
pr_off
2014-07-01 16:28:16 +02:00
}
2014-07-16 19:04:15 +02:00
2015-01-29 09:33:35 +01:00
pr_redln( ) { pr_red " $1 " ; outln; }
pr_red( ) {
[ [ " $COLOR " -eq 2 ] ] && out " \033[1;31m $1 " || pr_bold " $1 "
pr_off
2014-07-01 16:28:16 +02:00
}
2014-07-16 19:04:15 +02:00
2015-01-29 09:33:35 +01:00
pr_litemagentaln( ) { pr_litemagenta " $1 " ; outln; }
pr_litemagenta( ) {
[ [ " $COLOR " -eq 2 ] ] && out " \033[0;35m $1 " || pr_underline " $1 "
pr_off
}
2014-07-16 19:04:15 +02:00
2015-01-29 09:33:35 +01:00
pr_magentaln( ) { pr_magenta " $1 " ; outln; }
pr_magenta( ) {
[ [ " $COLOR " -eq 2 ] ] && out " \033[1;35m $1 " || pr_underline " $1 "
pr_off
2014-07-01 16:28:16 +02:00
}
2014-07-16 19:04:15 +02:00
2015-01-29 09:33:35 +01:00
pr_litecyanln( ) { pr_litecyan " $1 " ; outln; }
pr_litecyan( ) {
[ [ " $COLOR " -eq 2 ] ] && out " \033[0;36m $1 " || out " $1 "
pr_off
2014-07-01 16:28:16 +02:00
}
2014-07-16 19:04:15 +02:00
2015-01-29 09:33:35 +01:00
pr_cyanln( ) { pr_cyan " $1 " ; outln; }
pr_cyan( ) {
2014-11-25 13:12:24 +01:00
[ [ " $COLOR " = 2 ] ] && out " \033[1;36m $1 " || out " $1 "
2015-01-29 09:33:35 +01:00
pr_off
2014-07-01 16:28:16 +02:00
}
2014-07-16 19:04:15 +02:00
2015-01-29 09:33:35 +01:00
pr_greyln( ) { pr_grey " $1 " ; outln; }
pr_grey( ) {
[ [ " $COLOR " -eq 2 ] ] && out " \033[1;30m $1 " || out " $1 "
pr_off
2014-07-01 16:28:16 +02:00
}
2014-07-16 19:04:15 +02:00
2015-01-29 09:33:35 +01:00
pr_litegreyln( ) { pr_litegrey " $1 " ; outln; }
pr_litegrey( ) {
[ [ " $COLOR " -eq 2 ] ] && out " \033[0;37m $1 " || out " $1 "
pr_off
2014-07-01 16:28:16 +02:00
}
2014-07-16 19:04:15 +02:00
2015-01-29 09:33:35 +01:00
pr_litegreenln( ) { pr_litegreen " $1 " ; outln; }
pr_litegreen( ) {
[ [ " $COLOR " -eq 2 ] ] && out " \033[0;32m $1 " || out " $1 "
pr_off
2014-07-01 16:28:16 +02:00
}
2014-07-16 19:04:15 +02:00
2015-01-29 09:33:35 +01:00
pr_greenln( ) { pr_green " $1 " ; outln; }
pr_green( ) {
[ [ " $COLOR " -eq 2 ] ] && out " \033[1;32m $1 " || out " $1 "
pr_off
2014-07-01 16:28:16 +02:00
}
2014-07-16 19:04:15 +02:00
2015-01-29 09:33:35 +01:00
pr_brownln( ) { pr_brown " $1 " ; outln; }
pr_brown( ) {
[ [ " $COLOR " -eq 2 ] ] && out " \033[0;33m $1 " || out " $1 "
pr_off
2014-07-01 16:28:16 +02:00
}
2014-07-16 19:04:15 +02:00
2015-01-29 10:46:16 +01:00
pr_yellowln( ) { pr_yellow " $1 " ; outln; }
2015-01-29 09:33:35 +01:00
pr_yellow( ) {
[ [ " $COLOR " -eq 2 ] ] && out " \033[1;33m $1 " || out " $1 "
pr_off
2014-07-01 16:28:16 +02:00
}
2015-01-29 09:33:35 +01:00
pr_boldln( ) { pr_bold " $1 " ; outln; }
pr_bold( ) { [ [ " $COLOR " -ne 0 ] ] && out " \033[1m $1 " || out " $1 " ; pr_off; }
pr_underline( ) { [ [ " $COLOR " -ne 0 ] ] && out " \033[4m $1 " || out " $1 " ; pr_off; }
pr_boldandunder( ) { [ [ " $COLOR " -ne 0 ] ] && out " \033[1m\033[4m $1 " || out " $1 " ; pr_off; }
pr_reverse( ) { [ [ " $COLOR " -ne 0 ] ] && out " \033[7m $1 " || out " $1 " ; pr_off; }
### colorswitcher (see e.g. https://linuxtidbits.wordpress.com/2008/08/11/output-color-on-bash-scripts/
### http://www.tldp.org/HOWTO/Bash-Prompt-HOWTO/x405.html
if [ [ " $COLOR " -eq 2 ] ] ; then
red = $( tput setaf 1)
green = $( tput setaf 2)
yellow = $( tput setaf 3)
blue = $( tput setaf 4)
off = $( tput sgr0)
fi
2014-07-01 16:28:16 +02:00
2015-01-29 09:33:35 +01:00
if [ [ " $COLOR " -ge 1 ] ] ; then
bold = $( tput bold)
underline = $( tput sgr 0 1)
fi
2014-07-01 16:28:16 +02:00
2014-07-16 19:04:15 +02:00
2015-01-29 09:33:35 +01:00
###### function definitions
2014-07-01 16:28:16 +02:00
2015-02-11 09:43:04 +01:00
debugme( ) {
if [ [ $DEBUG -ge 2 ] ] ; then
echo " $@ "
" $@ "
else
:
fi
}
2014-12-18 09:33:24 +01:00
tmpfile_handle( ) {
2014-12-19 17:02:26 +01:00
if [ [ " $DEBUG " -eq 0 ] ] ; then
rm $TMPFILE
else
mv $TMPFILE " $TEMPDIR / $1 "
fi
2014-12-18 09:33:24 +01:00
}
2014-07-01 16:28:16 +02:00
2014-11-19 18:04:43 +01:00
# whether it is ok to offer/not to offer enc/cipher/version
2014-07-01 16:28:16 +02:00
ok( ) {
if [ " $2 " -eq 1 ] ; then
case $1 in
2015-01-29 09:33:35 +01:00
1) pr_redln "offered (NOT ok)" ; ; # 1 1
0) pr_greenln "not offered (OK)" ; ; # 0 1
2014-07-01 16:28:16 +02:00
esac
else
case $1 in
2015-01-29 09:33:35 +01:00
7) pr_brownln "not offered" ; ; # 7 0
6) pr_literedln "offered (NOT ok)" ; ; # 6 0
2015-01-29 10:46:16 +01:00
5) pr_litered "supported but couldn't detect a cipher" ; outln "(may need debugging)" ; ; # 5 5
2015-01-29 09:33:35 +01:00
4) pr_litegreenln "offered (OK)" ; ; # 4 0
3) pr_brownln "offered" ; ; # 3 0
2014-11-20 10:46:55 +01:00
2) outln "offered" ; ; # 2 0
2015-01-29 09:33:35 +01:00
1) pr_greenln "offered (OK)" ; ; # 1 0
0) pr_boldln "not offered" ; ; # 0 0
2014-07-01 16:28:16 +02:00
esac
fi
return $2
}
2014-11-30 01:30:20 +01:00
# ARG1= pid which is in the backgnd and we wait for ($2 seconds)
wait_kill( ) {
pid = $1
maxsleep = $2
while true; do
if ! ps ax | grep -v grep | grep -q $pid ; then
return 0 # didn't reach maxsleep yet
fi
sleep 1
maxsleep = ` expr $maxsleep - 1`
test $maxsleep -eq 0 && break
done # needs to be killed:
kill $pid >& 2 2>/dev/null
wait $pid 2>/dev/null
return 3 # killed
}
2014-07-01 16:28:16 +02:00
# in a nutshell: It's HTTP-level compression & an attack which works against any cipher suite and
# is agnostic to the version of TLS/SSL, more: http://www.breachattack.com/
2014-11-30 01:30:20 +01:00
# foreign referers are the important thing here!
2014-07-01 16:28:16 +02:00
breach( ) {
2015-01-29 09:33:35 +01:00
pr_bold " BREACH" ; out " (CVE-2013-3587) =HTTP Compression "
2015-01-14 12:23:53 +01:00
url = " $1 "
[ -z " $url " ] && url = "/"
2014-07-01 16:28:16 +02:00
if [ $SNEAKY -eq 0 ] ; then
referer = "Referer: http://google.com/" # see https://community.qualys.com/message/20360
useragent = "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)"
else
referer = " Referer: TLS/SSL-Tester from $SWURL "
useragent = "User-Agent: Mozilla/4.0 (X11; Linux x86_64; rv:42.0) Gecko/19700101 Firefox/42.0"
fi
(
$OPENSSL s_client -quiet -connect $NODEIP :$PORT $SNI << EOF
GET $url HTTP/1.1
Host: $NODE
$useragent
2015-02-15 13:14:11 +01:00
Accept: text/*
2014-07-01 16:28:16 +02:00
Accept-Language: en-US,en
Accept-encoding: gzip,deflate,compress
$referer
Connection: close
EOF
2014-11-30 01:30:20 +01:00
) & >$HEADERFILE_BREACH &
pid = $!
if wait_kill $pid $HEADER_MAXSLEEP ; then
result = ` cat $HEADERFILE_BREACH | grep -a '^Content-Encoding' | sed -e 's/^Content-Encoding//' -e 's/://' -e 's/ //g' `
result = ` echo $result | tr -cd '\40-\176' `
if [ -z $result ] ; then
2015-02-21 11:47:12 +01:00
pr_green "no HTTP compression (OK) "
2014-11-30 01:30:20 +01:00
ret = 0
else
2015-02-21 11:47:12 +01:00
pr_litered " NOT ok, uses $result compression "
2014-11-30 01:30:20 +01:00
ret = 1
fi
# Catch: any URL can be vulnerable. I am testing now only the root. URL!
outln " (only \" $url \" tested) "
2014-07-01 16:28:16 +02:00
else
2015-01-29 09:33:35 +01:00
pr_litemagentaln "failed (HTTP header request stalled)"
2014-11-30 01:30:20 +01:00
ret = 3
2014-07-01 16:28:16 +02:00
fi
2014-11-30 01:30:20 +01:00
return $ret
}
# determines whether the port has an HTTP service running or not (plain TLS, no STARTTLS)
runs_HTTP( ) {
# SNI is nonsense for !HTTP but fortunately SMTP and friends don't care
2015-02-15 13:14:11 +01:00
printf " GET / HTTP/1.1\r\nHost: $NODE \r\nUser-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)\r\nAccept: text/*\r\n\r\n " | $OPENSSL s_client -quiet -connect $NODE :$PORT $SNI & >$TMPFILE &
2014-11-30 01:30:20 +01:00
wait_kill $! $HEADER_MAXSLEEP
2015-02-13 16:01:46 +01:00
head $TMPFILE | grep -q ^HTTP && SERVICE = HTTP
head $TMPFILE | grep -q SMTP && SERVICE = SMTP
head $TMPFILE | grep -q POP && SERVICE = POP
head $TMPFILE | grep -q IMAP && SERVICE = IMAP
debugme head $TMPFILE
2014-11-30 01:30:20 +01:00
# $TMPFILE contains also a banner which we could use if there's a need for it
2015-02-13 16:01:46 +01:00
out " Service detected: "
2014-11-30 01:30:20 +01:00
case $SERVICE in
HTTP)
2015-02-13 16:01:46 +01:00
out " $SERVICE "
2015-02-12 13:40:53 +01:00
ret = 0 ; ;
2014-11-30 01:30:20 +01:00
IMAP| POP| SMTP)
2015-02-13 16:01:46 +01:00
out " $SERVICE , thus skipping HTTP specific checks "
2015-02-12 13:40:53 +01:00
ret = 0 ; ;
2015-02-13 16:01:46 +01:00
*) out " Couldn't determine what's running on port $PORT "
if [ [ $ASSUMING_HTTP -eq 1 ] ] ; then
SERVICE = HTTP
out " -- ASSUMING_HTTP set though"
ret = 0
else
out ", assuming not HTTP, skipping HTTP checks"
ret = 1
fi
; ;
2014-11-30 01:30:20 +01:00
esac
2014-07-01 16:28:16 +02:00
2015-02-13 16:01:46 +01:00
outln
2014-12-19 17:02:26 +01:00
tmpfile_handle $FUNCNAME .txt
2014-07-01 16:28:16 +02:00
return $ret
}
2014-10-15 13:10:06 +02:00
# Padding Oracle On Downgraded Legacy Encryption
poodle( ) {
2015-01-29 09:33:35 +01:00
pr_bold " POODLE " ; out "(CVE-2014-3566), experimental "
2014-10-15 13:10:06 +02:00
# w/o downgrade check as of now https://tools.ietf.org/html/draft-ietf-tls-downgrade-scsv-00 | TLS_FALLBACK_SCSV
$OPENSSL s_client -ssl3 $STARTTLS -connect $NODEIP :$PORT $SNI 2>$TMPFILE >/dev/null </dev/null
ret = $?
[ " $VERBERR " -eq 0 ] && cat $TMPFILE | egrep "error|failure" | egrep -v "unable to get local|verify error"
if [ $ret -eq 0 ] ; then
2015-02-21 11:47:12 +01:00
pr_litered "VULNERABLE (NOT ok)" ; out ", uses SSLv3 (no TLS_FALLBACK_SCSV mitigation tested)"
2014-10-15 13:10:06 +02:00
else
2015-01-29 09:33:35 +01:00
pr_green "not vulnerable (OK)"
2014-10-15 13:10:06 +02:00
fi
2014-10-17 22:16:37 +02:00
outln
2014-10-15 13:10:06 +02:00
2015-02-11 09:43:04 +01:00
tmpfile_handle $FUNCNAME .txt
2014-10-15 13:10:06 +02:00
return $ret
}
2014-07-01 16:28:16 +02:00
2015-01-14 09:48:44 +01:00
#problems not handled: chunked
2014-07-01 16:28:16 +02:00
http_header( ) {
2015-01-14 09:48:44 +01:00
[ -z " $1 " ] && url = "/" || url = " $1 "
2014-07-01 16:28:16 +02:00
if [ $SNEAKY -eq 0 ] ; then
2015-01-14 09:48:44 +01:00
referer = "Referer: http://google.com/"
2014-07-01 16:28:16 +02:00
useragent = "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)"
else
referer = " Referer: TLS/SSL-Tester from $SWURL "
useragent = "User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:42.0) Gecko/19700101 Firefox/42.0"
fi
(
$OPENSSL s_client -quiet -connect $NODEIP :$PORT $SNI << EOF
GET $url HTTP/1.1
Host: $NODE
2015-01-14 09:48:44 +01:00
Accept: text/html,application/xhtml+xml,application/xml; q = 0.9,*/*; q = 0.8
Accept-Language: en-us,en; q = 0.7,de-de; q = 0.3
2014-07-01 16:28:16 +02:00
$useragent
$referer
Connection: close
EOF
2014-11-30 01:30:20 +01:00
) & >$HEADERFILE &
pid = $!
if wait_kill $pid $HEADER_MAXSLEEP ; then
2015-02-13 16:01:46 +01:00
if ! egrep -iq "XML|HTML|DOCTYPE|HTTP|Connection" $HEADERFILE ; then
2015-02-21 11:47:12 +01:00
pr_litemagenta " likely HTTP header requests failed (#lines: $( cat $HEADERFILE | wc -l) ). "
outln "Rerun with DEBUG=1 and inspect \"http_header.txt\"\n"
2015-02-13 16:01:46 +01:00
debugme cat $HEADERFILE
ret = 7
fi
2014-11-30 01:30:20 +01:00
sed -e '/^<HTML/,$d' -e '/^<html/,$d' -e '/^<XML /,$d' -e '/<?XML /,$d' \
-e '/^<xml /,$d' -e '/<?xml /,$d' -e '/^<\!DOCTYPE/,$d' -e '/^<\!doctype/,$d' $HEADERFILE >$HEADERFILE .2
2014-07-01 16:28:16 +02:00
#### ^^^ Attention: the filtering for the html body only as of now, doesn't work for other content yet
2014-11-30 01:30:20 +01:00
mv $HEADERFILE .2 $HEADERFILE # sed'ing in place doesn't work with BSD and Linux simultaneously
ret = 0
else
2015-01-29 09:33:35 +01:00
pr_litemagentaln "failed (HTTP header request stalled)"
2014-11-30 01:30:20 +01:00
ret = 3
fi
2015-02-15 14:00:13 +01:00
if egrep -awq "301|302|^Location" $HEADERFILE ; then
redir2 = ` grep -a '^Location' $HEADERFILE | sed 's/Location: //' | tr -d '\r\n' `
outln " (got 30x to $redir2 , may be better try this URL?)\n "
fi
[ [ $DEBUG -eq 0 ] ] && rm $HEADERFILE .2 2>/dev/null
2015-02-13 16:01:46 +01:00
2014-11-30 01:30:20 +01:00
return $ret
2014-07-01 16:28:16 +02:00
}
2014-10-29 21:24:43 +01:00
includeSubDomains( ) {
2015-02-15 13:37:44 +01:00
if grep -aiqw includeSubDomains " $1 " ; then
2015-01-29 09:33:35 +01:00
pr_litegreen ", includeSubDomains"
2014-10-29 21:24:43 +01:00
else
2015-01-29 09:33:35 +01:00
pr_litecyan ", just this domain"
2014-10-29 21:24:43 +01:00
fi
}
2015-02-15 13:37:44 +01:00
preload( ) {
grep -aiqw preload " $1 " && pr_litegreen ", preload"
}
2014-07-01 16:28:16 +02:00
hsts( ) {
2014-11-30 01:30:20 +01:00
if [ ! -s $HEADERFILE ] ; then
2015-01-14 12:23:53 +01:00
http_header " $1 " || return 3
2014-11-30 01:30:20 +01:00
fi
2015-02-15 14:00:13 +01:00
pr_bold " HSTS "
2015-01-14 12:23:53 +01:00
grep -iaw '^Strict-Transport-Security' $HEADERFILE >$TMPFILE
2014-07-01 16:28:16 +02:00
if [ $? -eq 0 ] ; then
2015-01-14 12:23:53 +01:00
grep -aciw '^Strict-Transport-Security' $HEADERFILE | egrep -wq "1" || out "(two HSTS header, using 1st one) "
2014-10-08 01:03:14 +02:00
AGE_SEC = ` sed -e 's/[^0-9]*//g' $TMPFILE | head -1`
2014-07-01 16:28:16 +02:00
AGE_DAYS = ` expr $AGE_SEC \/ 86400`
if [ $AGE_DAYS -gt $HSTS_MIN ] ; then
2015-01-29 09:33:35 +01:00
pr_litegreen " $AGE_DAYS days \c " ; out " ( $AGE_SEC s) "
2014-07-01 16:28:16 +02:00
else
2015-01-29 09:33:35 +01:00
pr_brown " $AGE_DAYS days (< $HSTS_MIN is not good enough) "
2014-07-01 16:28:16 +02:00
fi
2014-10-29 21:24:43 +01:00
includeSubDomains " $TMPFILE "
2015-02-15 13:37:44 +01:00
preload " $TMPFILE " #FIXME: To be checked against: e.g. https://dxr.mozilla.org/mozilla-central/source/security/manager/boot/src/nsSTSPreloadList.inc and https://chromium.googlesource.com/chromium/src/+/master/net/http/transport_security_state_static.json
2014-10-29 21:24:43 +01:00
else
2015-01-29 23:20:58 +01:00
out "--"
2014-10-29 21:24:43 +01:00
fi
outln
2014-12-19 17:02:26 +01:00
tmpfile_handle $FUNCNAME .txt
2014-10-29 21:24:43 +01:00
return $?
}
hpkp( ) {
2014-11-30 01:30:20 +01:00
if [ ! -s $HEADERFILE ] ; then
2015-01-14 12:23:53 +01:00
http_header " $1 " || return 3
2014-11-30 01:30:20 +01:00
fi
2015-02-15 14:00:13 +01:00
pr_bold " HPKP "
2015-01-14 12:23:53 +01:00
egrep -aiw '^Public-Key-Pins|Public-Key-Pins-Report-Only' $HEADERFILE >$TMPFILE
2014-10-29 21:24:43 +01:00
if [ $? -eq 0 ] ; then
2015-01-14 12:23:53 +01:00
egrep -aciw '^Public-Key-Pins|Public-Key-Pins-Report-Only' $HEADERFILE | egrep -wq "1" || out "(two HPKP header, using 1st one) "
2014-10-29 21:24:43 +01:00
AGE_SEC = ` sed -e 's/\r//g' -e 's/^.*max-age=//' -e 's/;.*//' $TMPFILE `
AGE_DAYS = ` expr $AGE_SEC \/ 86400`
2014-12-08 10:32:51 +01:00
if [ $AGE_DAYS -ge $HPKP_MIN ] ; then
2015-01-29 09:33:35 +01:00
pr_litegreen " $AGE_DAYS days \c " ; out " ( $AGE_SEC s) "
2014-10-29 21:24:43 +01:00
else
2015-01-29 09:33:35 +01:00
pr_brown " $AGE_DAYS days (< $HPKP_MIN is not good enough) "
2014-10-29 21:24:43 +01:00
fi
includeSubDomains " $TMPFILE "
2015-02-15 13:37:44 +01:00
preload " $TMPFILE "
2014-10-29 21:24:43 +01:00
out ", fingerprints not checked"
2014-07-01 16:28:16 +02:00
else
2015-01-29 23:20:58 +01:00
out "--"
2014-07-01 16:28:16 +02:00
fi
2014-07-16 19:04:15 +02:00
outln
2014-12-19 17:02:26 +01:00
tmpfile_handle $FUNCNAME .txt
2014-07-01 16:28:16 +02:00
return $?
}
2015-01-23 12:01:32 +01:00
emphasize_numbers_in_headers( ) {
# see http://www.grymoire.com/Unix/Sed.html#uh-3
2015-01-29 09:33:35 +01:00
# outln "$1" | sed "s/[0-9]*/$yellow&$off/g"
outln " $1 " | sed " s/\([0-9]\)/ $yellow \1 $off /g "
2015-01-23 12:01:32 +01:00
}
2014-07-01 16:28:16 +02:00
serverbanner( ) {
2014-11-30 01:30:20 +01:00
if [ ! -s $HEADERFILE ] ; then
2015-01-14 12:23:53 +01:00
http_header " $1 " || return 3
2014-11-30 01:30:20 +01:00
fi
2015-02-15 14:00:13 +01:00
pr_bold " Server "
2015-01-14 12:23:53 +01:00
grep -ai '^Server' $HEADERFILE >$TMPFILE
2014-07-01 16:28:16 +02:00
if [ $? -eq 0 ] ; then
2014-07-16 19:04:15 +02:00
serverbanner = ` cat $TMPFILE | sed -e 's/^Server: //' -e 's/^server: //' `
2015-01-15 20:29:46 +01:00
if [ x" $serverbanner " = = "x\n" -o x" $serverbanner " = = "x\n\r" -o x" $serverbanner " = = "x" ] ; then
outln "banner exists but empty string"
else
2015-01-23 12:01:32 +01:00
emphasize_numbers_in_headers " $serverbanner "
2015-01-15 20:29:46 +01:00
fi
2014-07-01 16:28:16 +02:00
else
2015-02-13 16:01:46 +01:00
outln "no \"Server\" line in header, interesting!"
2014-07-01 16:28:16 +02:00
fi
2015-01-21 12:53:00 +01:00
tmpfile_handle $FUNCNAME .txt
return $?
}
applicationbanner( ) {
if [ ! -s $HEADERFILE ] ; then
http_header " $1 " || return 3
fi
2015-02-15 14:00:13 +01:00
pr_bold " Application "
2015-01-14 12:23:53 +01:00
# examples: dev.testssl.sh, php.net, asp.net , www.regonline.com
egrep -ai '^X-Powered-By|^X-AspNet-Version|^X-Runtime|^X-Version' $HEADERFILE >$TMPFILE
2014-07-01 16:28:16 +02:00
if [ $? -eq 0 ] ; then
#cat $TMPFILE | sed 's/^.*:/:/' | sed -e :a -e '$!N;s/\n:/ \n\ +/;ta' -e 'P;D' | sed 's/://g'
2015-01-29 09:33:35 +01:00
#sed 's/^/ /g' $TMPFILE | tr -t '\n\r' ' ' | sed "s/\([0-9]\)/$pr_red\1$off/g"
2015-01-23 12:01:32 +01:00
emphasize_numbers_in_headers " $( sed 's/^/ /g' $TMPFILE | tr -t '\n\r' ' ' ) "
2015-01-14 09:48:44 +01:00
#i=0
#cat $TMPFILE | sed 's/^/ /' | while read line; do
# out "$line"
# if [[ $i -eq 0 ]] ; then
# out " "
# i=1
# fi
#done
2014-07-01 16:28:16 +02:00
else
2015-01-29 23:20:58 +01:00
outln " (no banner at \" $url \") "
2014-07-01 16:28:16 +02:00
fi
2014-12-19 17:02:26 +01:00
tmpfile_handle $FUNCNAME .txt
2014-07-01 16:28:16 +02:00
return $?
}
2015-01-14 09:48:44 +01:00
cookieflags( ) { # ARG1: Path, ARG2: path
if [ ! -s $HEADERFILE ] ; then
http_header " $1 " || return 3
2014-11-30 01:30:20 +01:00
fi
2015-02-15 14:00:13 +01:00
pr_bold " Cookie(s) "
2015-01-14 12:23:53 +01:00
grep -ai '^Set-Cookie' $HEADERFILE >$TMPFILE
2014-07-01 16:28:16 +02:00
if [ $? -eq 0 ] ; then
2015-01-14 12:23:53 +01:00
nr_cookies = ` cat $TMPFILE | wc -l`
2015-01-29 23:20:58 +01:00
out " $nr_cookies issued: "
2015-01-14 12:23:53 +01:00
if [ $nr_cookies -gt 1 ] ; then
2015-02-07 17:30:36 +01:00
negative_word = "NONE"
2015-01-14 09:48:44 +01:00
else
2015-01-14 12:23:53 +01:00
negative_word = "NOT"
2014-07-01 16:28:16 +02:00
fi
2015-01-14 12:23:53 +01:00
nr_secure = ` grep -iac secure $TMPFILE `
case $nr_secure in
0) out " $negative_word secure, " ; ;
2015-01-29 09:33:35 +01:00
[ 123456789] ) pr_litegreen " $nr_secure / $nr_cookies " ; out "secure, " ; ;
2015-01-14 12:23:53 +01:00
esac
nr_httponly = ` grep -cai httponly $TMPFILE `
case $nr_httponly in
0) out " $negative_word HttpOnly " ; ;
2015-01-29 09:33:35 +01:00
[ 123456789] ) pr_litegreen " $nr_httponly / $nr_cookies " ; out "HttpOnly" ; ;
2015-01-14 12:23:53 +01:00
esac
2015-01-14 09:48:44 +01:00
else
2015-01-29 23:20:58 +01:00
out " (none issued at \" $url \") "
2014-07-01 16:28:16 +02:00
fi
2015-01-14 09:48:44 +01:00
outln
2014-12-19 17:02:26 +01:00
tmpfile_handle $FUNCNAME .txt
2014-11-30 01:30:20 +01:00
return 0
2014-07-01 16:28:16 +02:00
}
#FIXME: Access-Control-Allow-Origin, CSP, Upgrade, X-Frame-Options, X-XSS-Protection, X-Content-Type-Options
# https://en.wikipedia.org/wiki/List_of_HTTP_header_fields
# #1: string with 2 opensssl codes, HEXC= same in NSS/ssllab terminology
normalize_ciphercode( ) {
part1 = ` echo " $1 " | awk -F',' '{ print $1 }' `
part2 = ` echo " $1 " | awk -F',' '{ print $2 }' `
part3 = ` echo " $1 " | awk -F',' '{ print $3 }' `
if [ " $part1 " = = "0x00" ] ; then # leading 0x00
HEXC = $part2
else
part2 = ` echo $part2 | sed 's/0x//g' `
if [ -n " $part3 " ] ; then # a SSLv2 cipher has three parts
part3 = ` echo $part3 | sed 's/0x//g' `
fi
HEXC = " $part1 $part2 $part3 "
fi
2014-11-18 11:03:03 +01:00
HEXC = ` echo $HEXC | tr 'A-Z' 'a-z' | sed 's/0x/x/' ` #tolower + strip leading 0
2014-07-01 16:28:16 +02:00
return 0
}
prettyprint_local( ) {
2015-01-29 09:33:35 +01:00
pr_blue "--> Displaying all local ciphers" ;
2014-11-18 11:03:03 +01:00
if [ ! -z " $1 " ] ; then
2015-01-29 09:33:35 +01:00
pr_blue "matching word pattern " \" $1 \" " (ignore case)" ;
2014-07-01 16:28:16 +02:00
fi
2014-11-18 11:03:03 +01:00
outln "\n"
2014-07-01 16:28:16 +02:00
neat_header
2014-11-18 11:03:03 +01:00
if [ -z " $1 " ] ; then
$OPENSSL ciphers -V 'ALL:COMPLEMENTOFALL:@STRENGTH' | while read hexcode dash ciph sslvers kx auth enc mac export ; do
normalize_ciphercode $hexcode
neat_list $HEXC $ciph $kx $enc | strings
done
else
for arg in ` echo $@ | sed 's/,/ /g' ` ; do
$OPENSSL ciphers -V 'ALL:COMPLEMENTOFALL:@STRENGTH' | while read hexcode dash ciph sslvers kx auth enc mac export ; do
normalize_ciphercode $hexcode
neat_list $HEXC $ciph $kx $enc | strings | grep -wai " $arg "
done
done
fi
2014-07-16 19:04:15 +02:00
outln
2014-07-01 16:28:16 +02:00
return 0
}
# list ciphers (and makes sure you have them locally configured)
# arg[1]: cipher list (or anything else)
listciphers( ) {
2015-01-21 12:53:00 +01:00
$OPENSSL ciphers $1 & >$TMPFILE
2014-11-25 13:12:24 +01:00
ret = $?
2014-11-30 01:30:20 +01:00
[ [ $LOCERR -eq 1 ] ] && cat $TMPFILE
2014-12-19 17:02:26 +01:00
tmpfile_handle $FUNCNAME .txt
2014-11-25 13:12:24 +01:00
return $ret
2014-07-01 16:28:16 +02:00
}
# argv[1]: cipher list to test
# argv[2]: string on console
# argv[3]: ok to offer? 0: yes, 1: no
std_cipherlists( ) {
2014-07-16 19:04:15 +02:00
out " $2 " ;
2014-11-25 13:12:24 +01:00
if listciphers $1 ; then # is that locally available??
2014-11-30 01:30:20 +01:00
[ $SHOW_LOC_CIPH = "1" ] && out "local ciphers are: " && cat $TMPFILE | sed 's/:/, /g'
2014-07-16 19:04:15 +02:00
$OPENSSL s_client -cipher " $1 " $STARTTLS -connect $NODEIP :$PORT $SNI 2>$TMPFILE >/dev/null </dev/null
2014-07-01 16:28:16 +02:00
ret = $?
2015-02-04 09:48:34 +01:00
[ [ $DEBUG -ge 2 ] ] && cat $TMPFILE
2014-11-25 13:12:24 +01:00
case $3 in
0) # ok to offer
if [ [ $ret -eq 0 ] ] ; then # was offered
2015-01-29 09:33:35 +01:00
ok 1 0 # pr_green
2014-11-25 13:12:24 +01:00
else
ok 0 0 # black
fi ; ;
2) # not really bad
if [ [ $ret -eq 0 ] ] ; then
2015-02-03 23:20:59 +01:00
ok 2 0 # offered in normal
2014-11-25 13:12:24 +01:00
else
2015-02-03 23:20:59 +01:00
ok 2 0 # not offered also in normal
2014-11-25 13:12:24 +01:00
fi ; ;
*) # the ugly rest
if [ [ $ret -eq 0 ] ] ; then
2015-01-29 09:33:35 +01:00
ok 1 1 # was offered! --> pr_red
2014-11-25 13:12:24 +01:00
else
#ok 0 0 # was not offered, that's ok
2015-01-29 09:33:35 +01:00
ok 0 1 # was not offered --> pr_green
2014-11-25 13:12:24 +01:00
fi ; ;
esac
2014-12-19 17:02:26 +01:00
tmpfile_handle $FUNCNAME .txt
2014-07-01 16:28:16 +02:00
else
2014-10-29 21:24:43 +01:00
singlespaces = ` echo " $2 " | sed -e 's/ \+/ /g' -e 's/^ //' -e 's/ $//g' -e 's/ //g' `
2015-01-29 09:33:35 +01:00
pr_magentaln " Local problem: No $singlespaces configured in $OPENSSL "
2014-07-01 16:28:16 +02:00
fi
# we need lf in those cases:
2014-11-30 01:30:20 +01:00
[ [ $LOCERR -eq 1 ] ] && echo
2015-02-04 09:48:34 +01:00
[ [ $DEBUG -ge 2 ] ] && echo
2014-07-01 16:28:16 +02:00
}
2014-09-16 22:18:09 +02:00
2014-07-01 16:28:16 +02:00
# sockets inspired by http://blog.chris007.de/?p=238
2014-11-27 21:33:33 +01:00
# ARG1: hexbyte with a leading comma (!!), seperated by commas
# ARG2: sleep
2014-07-01 16:28:16 +02:00
socksend( ) {
2014-11-27 21:33:33 +01:00
# the following works under BSD and Linux, which is quite tricky. So don't mess with it unless you're really sure what you do
data = ` echo " $1 " | sed -e 's/# .*$//g' -e 's/ //g' | sed -E 's/^[[:space:]]+//; s/[[:space:]]+$//; /^$/d' | sed 's/,/\\\/g' | tr -d '\n' `
2015-01-21 12:53:00 +01:00
[ [ $DEBUG -ge 4 ] ] && echo " \" $data \" "
2014-11-27 21:33:33 +01:00
printf -- " $data " >& 5 2>/dev/null &
sleep $2
2014-07-01 16:28:16 +02:00
}
2014-09-16 22:18:09 +02:00
2014-07-01 16:28:16 +02:00
sockread( ) {
2014-11-18 00:26:58 +01:00
[ " x $2 " = "x" ] && maxsleep = $MAX_WAITSOCK || maxsleep = $2
2014-09-16 22:18:09 +02:00
ret = 0
ddreply = ` mktemp /tmp/ddreply.XXXXXX` || exit 7
dd bs = $1 of = $ddreply 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 1
maxsleep = ` expr $maxsleep - 1`
test $maxsleep -eq 0 && break
done
2015-01-29 09:33:35 +01:00
#FIXME: cleanup, we have extra function for this now
2014-11-30 01:30:20 +01:00
2014-09-16 22:18:09 +02:00
if ps ax | grep -v grep | grep -q $pid ; then
2014-10-08 14:30:31 +02:00
# time's up and dd is still alive --> timeout
kill $pid
2014-09-16 22:18:09 +02:00
wait $pid 2>/dev/null
ret = 3 # means killed
fi
SOCKREPLY = ` cat $ddreply `
rm $ddreply
return $ret
2014-07-01 16:28:16 +02:00
}
show_rfc_style( ) {
2014-11-17 18:49:56 +01:00
[ ! -r " $MAP_RFC_FNAME " ] && return 1
2014-11-18 01:36:29 +01:00
RFCname = ` grep -iw $1 " $MAP_RFC_FNAME " | sed -e 's/^.*TLS/TLS/' -e 's/^.*SSL/SSL/' `
2014-11-30 01:30:20 +01:00
[ [ -n " $RFCname " ] ] && out " $RFCname "
2014-11-17 18:49:56 +01:00
return 0
2014-07-01 16:28:16 +02:00
}
neat_header( ) {
2014-11-18 10:29:11 +01:00
outln " Hexcode Cipher Suite Name (OpenSSL) KeyExch. Encryption Bits ${ MAP_RFC_FNAME : + Cipher Suite Name (RFC) } "
2014-11-18 23:14:17 +01:00
outln " %s------------------------------------------------------------------------- ${ MAP_RFC_FNAME : +---------------------------------------------- } "
2014-07-01 16:28:16 +02:00
}
neat_list( ) {
kx = ` echo $3 | sed 's/Kx=//g' `
enc = ` echo $4 | sed 's/Enc=//g' `
2014-11-18 01:36:29 +01:00
strength = ` echo $enc | sed -e 's/.*(//' -e 's/)//' ` # strength = encryption bits
strength = ` echo $strength | sed -e 's/ChaCha20-Poly1305/ly1305/g' ` # workaround for empty bits ChaCha20-Poly1305
enc = ` echo $enc | sed -e 's/(.*)//g' -e 's/ChaCha20-Poly1305/ChaCha20-Po/g' ` # workaround for empty bits ChaCha20-Poly1305
2014-07-01 16:28:16 +02:00
echo " $export " | grep -iq export && strength = " $strength ,export "
2014-11-27 21:33:33 +01:00
printf -- " %-7s %-30s %-10s %-11s%-11s ${ MAP_RFC_FNAME : + %-48s } ${ SHOW_EACH_C : + } " " $1 " " $2 " " $kx " " $enc " " $strength " " $( show_rfc_style $HEXC ) "
2014-07-01 16:28:16 +02:00
}
2014-08-29 14:57:20 +02:00
test_just_one( ) {
2015-01-29 09:33:35 +01:00
pr_blue "--> Testing single cipher with word pattern " \" $1 \" " (ignore case)" ; outln "\n"
2014-08-29 14:57:20 +02:00
neat_header
2014-11-02 23:37:17 +01:00
for arg in ` echo $@ | sed 's/,/ /g' ` ; do
2014-11-17 18:49:56 +01:00
# 1st check whether openssl has cipher or not
2014-11-02 23:37:17 +01:00
$OPENSSL ciphers -V 'ALL:COMPLEMENTOFALL:@STRENGTH' | while read hexcode dash ciph sslvers kx auth enc mac export ; do
normalize_ciphercode $hexcode
2014-11-18 01:36:29 +01:00
neat_list $HEXC $ciph $kx $enc | strings | grep -qwai " $arg "
2014-11-02 23:37:17 +01:00
if [ $? -eq 0 ] ; then
$OPENSSL s_client -cipher $ciph $STARTTLS -connect $NODEIP :$PORT $SNI & >$TMPFILE </dev/null
ret = $?
neat_list $HEXC $ciph $kx $enc
2014-08-29 14:57:20 +02:00
if [ $ret -eq 0 ] ; then
2015-01-29 09:33:35 +01:00
pr_cyan " available"
2014-08-29 14:57:20 +02:00
else
out " not a/v"
fi
2014-11-02 23:37:17 +01:00
outln
2014-08-29 14:57:20 +02:00
fi
done
done
2014-11-02 23:37:17 +01:00
outln
2014-12-19 17:02:26 +01:00
tmpfile_handle $FUNCNAME .txt
2014-08-29 14:57:20 +02:00
return 0
}
2014-07-01 16:28:16 +02:00
# test for all ciphers locally configured (w/o distinguishing whether they are good or bad
allciphers( ) {
2014-12-21 00:47:23 +01:00
nr_ciphers = ` $OPENSSL ciphers 'ALL:COMPLEMENTOFALL:@STRENGTH' | sed 's/:/ /g' | wc -w`
2015-01-29 09:33:35 +01:00
pr_blue " --> Testing all locally available $nr_ciphers ciphers against the server " ; outln "\n"
2014-07-01 16:28:16 +02:00
neat_header
2014-12-21 00:47:23 +01:00
2014-07-01 16:28:16 +02:00
$OPENSSL ciphers -V 'ALL:COMPLEMENTOFALL:@STRENGTH' | while read hexcode n ciph sslvers kx auth enc mac export; do
2014-12-21 00:47:23 +01:00
# FIXME: e.g. OpenSSL < 1.0 doesn't understand "-V" --> we can't do anything about it!
2014-07-01 16:28:16 +02:00
$OPENSSL s_client -cipher $ciph $STARTTLS -connect $NODEIP :$PORT $SNI & >$TMPFILE </dev/null
ret = $?
if [ $ret -ne 0 ] && [ " $SHOW_EACH_C " -eq 0 ] ; then
continue # no successful connect AND not verbose displaying each cipher
fi
normalize_ciphercode $hexcode
neat_list $HEXC $ciph $kx $enc
if [ " $SHOW_EACH_C " -ne 0 ] ; then
if [ $ret -eq 0 ] ; then
2015-01-29 09:33:35 +01:00
pr_cyan " available"
2014-07-01 16:28:16 +02:00
else
2014-07-16 19:04:15 +02:00
out " not a/v"
2014-07-01 16:28:16 +02:00
fi
fi
2014-07-16 19:04:15 +02:00
outln
2014-12-19 17:02:26 +01:00
tmpfile_handle $FUNCNAME .txt
2014-07-01 16:28:16 +02:00
done
return 0
}
2014-07-16 19:04:15 +02:00
2014-07-01 16:28:16 +02:00
# test for all ciphers per protocol locally configured (w/o distinguishing whether they are good or bad
cipher_per_proto( ) {
2015-01-29 09:33:35 +01:00
pr_blue "--> Testing all locally available ciphers per protocol against the server" ; outln "\n"
2014-07-01 16:28:16 +02:00
neat_header
2014-07-16 19:04:15 +02:00
outln " -ssl2 SSLv2\n -ssl3 SSLv3\n -tls1 TLSv1\n -tls1_1 TLSv1.1\n -tls1_2 TLSv1.2" | while read proto prtext; do
2014-07-01 16:28:16 +02:00
locally_supported " $proto " " $prtext " || continue
2014-07-16 19:04:15 +02:00
outln
2014-07-01 16:28:16 +02:00
$OPENSSL ciphers $proto -V 'ALL:COMPLEMENTOFALL:@STRENGTH' | while read hexcode n ciph sslvers kx auth enc mac export; do
$OPENSSL s_client -cipher $ciph $proto $STARTTLS -connect $NODEIP :$PORT $SNI & >$TMPFILE </dev/null
ret = $?
if [ $ret -ne 0 ] && [ " $SHOW_EACH_C " -eq 0 ] ; then
continue # no successful connect AND not verbose displaying each cipher
fi
normalize_ciphercode $hexcode
neat_list $HEXC $ciph $kx $enc
if [ " $SHOW_EACH_C " -ne 0 ] ; then
if [ $ret -eq 0 ] ; then
2015-01-29 09:33:35 +01:00
pr_cyan " available"
2014-07-01 16:28:16 +02:00
else
2014-07-16 19:04:15 +02:00
out " not a/v"
2014-07-01 16:28:16 +02:00
fi
fi
2014-07-16 19:04:15 +02:00
outln
2014-12-19 17:02:26 +01:00
tmpfile_handle $FUNCNAME .txt
2014-07-01 16:28:16 +02:00
done
done
2014-07-16 19:04:15 +02:00
2014-07-01 16:28:16 +02:00
return 0
}
locally_supported( ) {
2014-07-16 19:04:15 +02:00
out " $2 "
2014-07-01 16:28:16 +02:00
$OPENSSL s_client " $1 " 2>& 1 | grep -q "unknown option"
if [ $? -eq 0 ] ; then
2015-01-29 09:33:35 +01:00
pr_magentaln " Local problem: $OPENSSL doesn't support \"s_client $1 \" "
2014-11-19 17:08:59 +01:00
ret = 7
2014-07-01 16:28:16 +02:00
else
2014-11-19 17:08:59 +01:00
ret = 0
2014-07-01 16:28:16 +02:00
fi
2014-11-19 17:08:59 +01:00
return $ret
2014-07-01 16:28:16 +02:00
}
2014-12-21 23:22:50 +01:00
testversion( ) {
2014-11-19 18:04:43 +01:00
local sni = $SNI
[ " x $1 " = "x-ssl2" ] && sni = "" # newer openssl throw an error if SNI with SSLv2
$OPENSSL s_client -state $1 $STARTTLS -connect $NODEIP :$PORT $sni & >$TMPFILE </dev/null
2014-07-01 16:28:16 +02:00
ret = $?
[ " $VERBERR " -eq 0 ] && cat $TMPFILE | egrep "error|failure" | egrep -v "unable to get local|verify error"
2014-11-19 17:08:59 +01:00
if grep -q "no cipher list" $TMPFILE ; then
2014-11-19 18:04:43 +01:00
ret = 5
2014-11-19 17:08:59 +01:00
fi
2014-12-19 17:02:26 +01:00
tmpfile_handle $FUNCNAME .txt
2014-07-01 16:28:16 +02:00
return $ret
}
testprotohelper( ) {
if locally_supported " $1 " " $2 " ; then
2014-12-21 23:22:50 +01:00
testversion " $1 " " $2 "
2014-07-01 16:28:16 +02:00
return $?
else
return 7
fi
}
runprotocols( ) {
2015-01-29 09:33:35 +01:00
pr_blue "--> Testing Protocols" ; outln "\n"
2015-01-29 23:24:49 +01:00
if [ $SSL_NATIVE -eq 1 ] || [ -n " $STARTTLS " ] ; then
2015-01-29 10:46:16 +01:00
testprotohelper "-ssl2" " SSLv2 "
case $? in
0) ok 1 1 ; ; # pr_red
5) ok 5 5 ; ; # protocol ok, but no cipher
1) ok 0 1 ; ; # pr_green "not offered (ok)"
7) ; ; # no local support
esac
else
sslv2_sockets
fi
2014-07-01 16:28:16 +02:00
2014-11-19 17:08:59 +01:00
testprotohelper "-ssl3" " SSLv3 "
2014-11-19 18:04:43 +01:00
case $? in
0) ok 6 0 ; ; # poodle hack"
2015-01-29 09:33:35 +01:00
1) ok 0 1 ; ; # pr_green "not offered (ok)"
2014-11-19 18:04:43 +01:00
5) ok 5 5 ; ; # protocol ok, but no cipher
7) ; ; # no local support
esac
2014-07-01 16:28:16 +02:00
2014-11-19 17:08:59 +01:00
testprotohelper "-tls1" " TLSv1 "
2014-11-19 18:04:43 +01:00
case $? in
2015-02-03 23:20:59 +01:00
0) ok 2 0 ; ; # no GCM, thus only normal print
2014-11-19 18:04:43 +01:00
1) ok 0 0 ; ;
5) ok 5 5 ; ; # protocol ok, but no cipher
7) ; ; # no local support
esac
2014-07-01 16:28:16 +02:00
2014-11-19 17:08:59 +01:00
testprotohelper "-tls1_1" " TLSv1.1 "
2014-11-19 18:04:43 +01:00
case $? in
2015-02-03 23:20:59 +01:00
0) ok 2 0 ; ; # normal print
2014-11-20 10:46:55 +01:00
1) ok 7 0 ; ; # no GCM, penalty
2014-11-19 18:04:43 +01:00
5) ok 5 5 ; ; # protocol ok, but no cipher
7) ; ; # no local support
esac
2014-07-01 16:28:16 +02:00
2014-11-19 17:08:59 +01:00
testprotohelper "-tls1_2" " TLSv1.2 "
2014-11-19 18:04:43 +01:00
case $? in
0) ok 1 0 ; ;
2014-11-20 10:46:55 +01:00
1) ok 7 0 ; ; # no GCM, penalty
2014-11-19 18:04:43 +01:00
5) ok 5 5 ; ; # protocol ok, but no cipher
7) ; ; # no local support
esac
2014-11-19 17:08:59 +01:00
2014-07-01 16:28:16 +02:00
return 0
}
run_std_cipherlists( ) {
2014-07-16 19:04:15 +02:00
outln
2015-01-29 09:33:35 +01:00
pr_blue "--> Testing standard cipher lists" ; outln "\n"
2014-07-01 16:28:16 +02:00
# see man ciphers
std_cipherlists NULL:eNULL " Null Cipher " 1
std_cipherlists aNULL " Anonymous NULL Cipher " 1
std_cipherlists ADH " Anonymous DH Cipher " 1
2015-02-21 10:38:04 +01:00
#if [[ "$OSSL_VER" = *chacha* ]]; then
#out " 40 Bit encryption "; pr_magentaln "Local problem: $OPENSSL has a bug here"
#else
2015-02-12 09:32:47 +01:00
std_cipherlists EXPORT40 " 40 Bit encryption " 1
2015-02-21 10:38:04 +01:00
#fi
2014-07-01 16:28:16 +02:00
std_cipherlists EXPORT56 " 56 Bit encryption " 1
2015-02-21 10:38:04 +01:00
#if [[ "$OSSL_VER" = *chacha* ]]; then
# out " Export Cipher (general) "; pr_magentaln "Local problem: $OPENSSL has a bug here"
#else
2015-02-12 09:32:47 +01:00
std_cipherlists EXPORT " Export Cipher (general) " 1
2015-02-21 10:38:04 +01:00
#fi
2014-07-01 16:28:16 +02:00
std_cipherlists LOW " Low (<=64 Bit) " 1
std_cipherlists DES " DES Cipher " 1
std_cipherlists 3DES " Triple DES Cipher " 2
std_cipherlists "MEDIUM:!NULL:!aNULL:!SSLv2" " Medium grade encryption " 2
std_cipherlists "HIGH:!NULL:!aNULL" " High grade encryption " 0
return 0
}
2014-12-21 00:47:23 +01:00
openssl_error( ) {
2015-01-29 09:33:35 +01:00
pr_magenta " $OPENSSL returned an error. This shouldn't happen. "
2014-12-21 00:47:23 +01:00
outln "continuing anyway"
return 0
}
2014-12-18 09:33:24 +01:00
2014-12-21 00:47:23 +01:00
server_preference( ) {
list1 = "DES-CBC3-SHA:RC4-MD5:DES-CBC-SHA:RC4-SHA:AES128-SHA:AES128-SHA:AES256-SHA:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:DHE-DSS-AES128-SHA:DHE-DSS-AES128-SHA:DHE-DSS-AES256-SHA:ECDH-RSA-DES-CBC3-SHA:ECDH-RSA-AES128-SHA:ECDH-RSA-AES256-SHA:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:DHE-DSS-AES256-GCM-SHA384"
outln;
2015-01-29 09:33:35 +01:00
pr_blue "--> Testing server preferences" ; outln "\n"
2014-12-21 00:47:23 +01:00
$OPENSSL s_client $STARTTLS -cipher $list1 -connect $NODEIP :$PORT $SNI </dev/null 2>/dev/null >$TMPFILE
2014-07-01 16:28:16 +02:00
if [ $? -ne 0 ] ; then
2014-12-21 00:47:23 +01:00
openssl_error
ret = 6
2014-07-01 16:28:16 +02:00
else
2014-12-21 00:47:23 +01:00
cipher1 = ` grep -w Cipher $TMPFILE | egrep -vw "New|is" | sed -e 's/^ \+Cipher \+://' -e 's/ //g' `
2015-01-29 09:33:35 +01:00
list2 = ` echo $list1 | tr ':' '\n' | sort -r | tr '\n' ':' ` # pr_reverse the list
2014-12-21 00:47:23 +01:00
$OPENSSL s_client $STARTTLS -cipher $list2 -connect $NODEIP :$PORT $SNI </dev/null 2>/dev/null >$TMPFILE
cipher2 = ` grep -w Cipher $TMPFILE | egrep -vw "New|is" | sed -e 's/^ \+Cipher \+://' -e 's/ //g' `
out " Has server cipher order? "
if [ [ " $cipher1 " != " $cipher2 " ] ] ; then
2015-02-21 11:47:12 +01:00
pr_litered "nope (NOT ok)"
2014-12-21 00:47:23 +01:00
remark4default_cipher = " (limited sense as client will pick)"
else
2015-01-29 09:33:35 +01:00
pr_green "yes (OK)"
2014-12-21 00:47:23 +01:00
remark4default_cipher = ""
fi
2015-02-04 09:48:34 +01:00
[ [ $DEBUG -ge 2 ] ] && out " $cipher1 | $cipher2 "
2014-12-21 00:47:23 +01:00
outln
$OPENSSL s_client $STARTTLS -connect $NODEIP :$PORT $SNI </dev/null 2>/dev/null >$TMPFILE
2014-12-18 09:33:24 +01:00
out " Negotiated protocol "
2014-12-21 00:47:23 +01:00
default_proto = ` grep -w "Protocol" $TMPFILE | sed -e 's/^.*Protocol.*://' -e 's/ //g' `
case " $default_proto " in
2015-01-29 09:33:35 +01:00
*TLSv1.2) pr_greenln $default_proto ; ;
*TLSv1.1) pr_litegreenln $default_proto ; ;
2014-12-21 00:47:23 +01:00
*TLSv1) outln $default_proto ; ;
2015-01-29 09:33:35 +01:00
*SSLv2) pr_redln $default_proto ; ;
*SSLv3) pr_redln $default_proto ; ;
2014-12-21 00:47:23 +01:00
*) outln " FIXME: $default_proto " ; ;
2014-07-01 16:28:16 +02:00
esac
2014-12-21 00:47:23 +01:00
2014-12-18 09:33:24 +01:00
out " Negotiated cipher "
2014-12-21 00:47:23 +01:00
default_cipher = ` grep -w "Cipher" $TMPFILE | egrep -vw "New|is" | sed -e 's/^.*Cipher.*://' -e 's/ //g' `
case " $default_cipher " in
2015-01-29 09:33:35 +01:00
*NULL*| *EXP*) pr_red " $default_cipher " ; ;
*RC4*) pr_litered " $default_cipher " ; ;
*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
*CHACHA20*) pr_green " $default_cipher " ; ; # best ones
2015-01-29 10:46:16 +01:00
ECDHE*AES*) pr_yellow " $default_cipher " ; ; # it's CBC. --> lucky13
2014-12-21 00:47:23 +01:00
*) out " $default_cipher " ; ;
2014-07-01 16:28:16 +02:00
esac
2014-12-21 00:47:23 +01:00
outln " $remark4default_cipher "
2014-07-01 16:28:16 +02:00
2014-12-21 23:22:50 +01:00
out " Negotiated cipher per proto $remark4default_cipher "
i = 1
for p in sslv2 ssl3 tls1 tls1_1 tls1_2; do
# proto-check b4!
$OPENSSL s_client $STARTTLS -" $p " -connect $NODEIP :$PORT $SNI </dev/null 2>/dev/null >$TMPFILE
if [ $ret -eq 0 ] ; then
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] } = = "0000" ] ] && cipher[ i] = "" # Hack!
2015-02-04 09:48:34 +01:00
[ [ $DEBUG -ge 2 ] ] && outln " Default cipher for ${ proto [i] } : ${ cipher [i] } "
2014-12-21 23:22:50 +01:00
else
proto[ i] = ""
cipher[ i] = ""
fi
i = ` expr $i + 1`
done
if spdy_pre ; then # is NPN/SPDY supported and is this no STARTTLS?
$OPENSSL s_client -host $NODE -port $PORT -nextprotoneg " $NPN_PROTOs " </dev/null 2>/dev/null >$TMPFILE
if [ $? -eq 0 ] ; then
proto[ i] = ` grep -aw "Next protocol" $TMPFILE | sed -e 's/^Next protocol://' -e 's/(.)//' -e 's/ //g' `
if [ -z " ${ proto [i] } " ] ; then
cipher[ i] = ""
else
cipher[ i] = ` grep -aw "Cipher" $TMPFILE | egrep -vw "New|is" | sed -e 's/^ \+Cipher \+://' -e 's/ //g' `
2015-02-04 09:48:34 +01:00
[ [ $DEBUG -ge 2 ] ] && outln " Default cipher for ${ proto [i] } : ${ cipher [i] } "
2014-12-21 23:22:50 +01:00
fi
fi
fi
for i in 1 2 3 4 5 6; do
if [ [ -n " ${ cipher [i] } " ] ] ; then # cipher nicht leer
if [ [ -z " ${ cipher [i-1] } " ] ] ; then # der davor leer
2015-01-29 09:33:35 +01:00
outln
printf -- " %-30s %s" " ${ cipher [i] } : " " ${ proto [i] } " # beides ausgeben
2014-12-21 23:22:50 +01:00
else # davor nihct leer
2015-01-29 09:33:35 +01:00
if [ [ " ${ cipher [i-1] } " = = " ${ cipher [i] } " ] ] ; then # und bei vorigem Protokoll selber cipher
out " , ${ proto [i] } " # selber Cipher --> Nur Protokoll dahinter
else
outln
printf -- " %-30s %s" " ${ cipher [i] } : " " ${ proto [i] } " # beides ausgeben
fi
2014-12-21 23:22:50 +01:00
fi
fi
done
2014-12-21 00:47:23 +01:00
fi
2014-12-21 23:22:50 +01:00
outln
2014-12-21 00:47:23 +01:00
2015-01-29 09:33:35 +01:00
tmpfile_handle $FUNCNAME .txt
2014-12-21 00:47:23 +01:00
return 0
}
server_defaults( ) {
outln
2015-01-29 09:33:35 +01:00
pr_blue "--> Testing server defaults (Server Hello)" ; outln "\n"
2014-12-21 00:47:23 +01:00
localtime = ` date "+%s" `
# throwing every cipher/protocol at the server and displaying its pick
$OPENSSL s_client $STARTTLS -connect $NODEIP :$PORT $SNI -tlsextdebug -status </dev/null 2>/dev/null >$TMPFILE
ret = $?
$OPENSSL s_client $STARTTLS -connect $NODEIP :$PORT $SNI 2>/dev/null </dev/null | awk '/-----BEGIN/,/-----END/ { print $0 }' >$HOSTCERT
if [ $? -ne 0 ] || [ $ret -ne 0 ] ; then
openssl_error
ret = 6
else
2014-12-18 09:33:24 +01:00
out " TLS server extensions "
2014-07-01 16:28:16 +02:00
extensions = ` grep -w "^TLS server extension" $TMPFILE | sed -e 's/^TLS server extension \"//' -e 's/\".*$/,/g' `
if [ -z " $extensions " ] ; then
2014-07-16 19:04:15 +02:00
outln "(none)"
2014-07-01 16:28:16 +02:00
else
2014-07-16 19:04:15 +02:00
echo $extensions | sed 's/,$//' # remove last comma
2014-07-01 16:28:16 +02:00
fi
2014-12-18 09:33:24 +01:00
out " Session Tickets RFC 5077 "
2014-07-01 16:28:16 +02:00
sessticket_str = ` grep -w "session ticket" $TMPFILE | grep lifetime`
if [ -z " $sessticket_str " ] ; then
2014-07-16 19:04:15 +02:00
outln "(none)"
2014-07-01 16:28:16 +02:00
else
lifetime = ` echo $sessticket_str | grep lifetime | sed 's/[A-Za-z:() ]//g' `
unit = ` echo $sessticket_str | grep lifetime | sed -e 's/^.*' " $lifetime " '//' -e 's/[ ()]//g' `
2014-07-16 19:04:15 +02:00
outln " $lifetime $unit "
2014-07-01 16:28:16 +02:00
fi
2014-08-29 14:57:20 +02:00
2014-12-18 09:33:24 +01:00
out " Server key size "
keysize = ` grep -w "^Server public key is" $TMPFILE | sed -e 's/^Server public key is //' `
if [ -z " $keysize " ] ; then
outln "(couldn't determine)"
else
case " $keysize " in
2015-01-29 09:33:35 +01:00
1024*) pr_brownln " $keysize " ; ;
2014-12-18 09:33:24 +01:00
2048*) outln " $keysize " ; ;
2015-01-29 09:33:35 +01:00
4096*) pr_litegreenln " $keysize " ; ;
2014-12-18 09:33:24 +01:00
*) outln " $keysize " ; ;
esac
fi
# google seems to have EC keys which displays as 256 Bit
out " Signature Algorithm "
algo = ` $OPENSSL x509 -in $HOSTCERT -noout -text | grep "Signature Algorithm" | sed 's/^.*Signature Algorithm: //' | sort -u `
case $algo in
2015-01-29 09:33:35 +01:00
sha1WithRSAEncryption) pr_brownln "SHA1withRSA" ; ;
sha256WithRSAEncryption) pr_litegreenln "SHA256withRSA" ; ;
sha512WithRSAEncryption) pr_litegreenln "SHA512withRSA" ; ;
md5*) pr_redln "MD5" ; ;
2014-12-18 09:33:24 +01:00
*) outln " $algo " ; ;
esac
# old, but interesting: https://blog.hboeck.de/archives/754-Playing-with-the-EFF-SSL-Observatory.html
2015-02-03 23:46:47 +01:00
out " Fingerprint / Serial "
2015-02-15 12:58:51 +01:00
outln " $( $OPENSSL x509 -noout -in $HOSTCERT -fingerprint -sha1 | sed 's/Fingerprint=//' | sed 's/://g' ) / $( $OPENSSL x509 -noout -in $HOSTCERT -serial | sed 's/serial=//' ) "
outln " $( $OPENSSL x509 -noout -in $HOSTCERT -fingerprint -sha256 | sed 's/Fingerprint=//' | sed 's/://g' ) "
2015-02-03 23:46:47 +01:00
2014-12-18 09:33:24 +01:00
out " Common Name (CN) "
CN = ` $OPENSSL x509 -in $HOSTCERT -noout -subject | sed 's/subject= //' | sed -e 's/^.*CN=//' -e 's/\/emailAdd.*//' `
2014-12-23 09:59:03 +01:00
out " $CN "
2014-12-18 09:33:24 +01:00
2014-12-23 09:59:03 +01:00
CN_nosni = ` $OPENSSL s_client $STARTTLS -connect $NODEIP :$PORT 2>/dev/null </dev/null | awk '/-----BEGIN/,/-----END/ { print $0 }' | \
$OPENSSL x509 -noout -subject | sed 's/subject= //' | sed -e 's/^.*CN=//' -e 's/\/emailAdd.*//' `
2015-02-04 09:48:34 +01:00
[ [ $DEBUG -ge 2 ] ] && out " $NODE | $CN | $CN_nosni "
2014-12-23 09:59:03 +01:00
if [ [ $NODE = = $CN_nosni ] ] ; then
outln " (works w/o SNI)"
else
outln " (CN response to request w/o SNI: ' $CN_nosni ') "
fi
SAN = ` $OPENSSL x509 -in $HOSTCERT -noout -text | grep -A3 "Subject Alternative Name" | grep "DNS:" | \
sed -e 's/DNS://g' -e 's/ //g' -e 's/,/\n/g' -e 's/othername:<unsupported>//g' `
# ^^^ CACert
2014-12-19 07:12:20 +01:00
[ x" $SAN " != "x" ] && SAN = ` echo " $SAN " | sed -e ':a' -e 'N' -e '$!ba' -e 's/\n/ /g' ` && outln " subjectAltName (SAN) $SAN "
2014-12-18 09:33:24 +01:00
# replace line feed by " "
out " Issuer "
issuer = ` $OPENSSL x509 -in $HOSTCERT -noout -issuer | sed -e 's/^.*CN=//g' -e 's/\/.*$//g' `
issuer_o = ` $OPENSSL x509 -in $HOSTCERT -noout -issuer | sed 's/^.*O=//g' | sed 's/\/.*$//g' `
2014-12-23 09:59:03 +01:00
if $OPENSSL x509 -in $HOSTCERT -noout -issuer | grep -q 'C=' ; then
issuer_c = ` $OPENSSL x509 -in $HOSTCERT -noout -issuer | sed 's/^.*C=//g' | sed 's/\/.*$//g' `
else
issuer_c = "" # CACert would have 'issuer= ' here otherwise
fi
2014-12-21 00:47:23 +01:00
if [ " $issuer_o " = = "issuer=" ] || [ " $issuer " = = " $CN " ] ; then
2015-01-29 09:33:35 +01:00
pr_redln "selfsigned (not OK)"
2014-12-21 00:47:23 +01:00
else
2014-12-23 09:59:03 +01:00
[ " $issuer_c " = = "" ] && \
outln " $issuer (' $issuer_o ') " || \
outln " $issuer (' $issuer_o ' from ' $issuer_c ') "
2014-12-21 00:47:23 +01:00
fi
2014-12-18 09:33:24 +01:00
out " Certificate Expiration "
expire = ` $OPENSSL x509 -in $HOSTCERT -checkend 0`
if ! echo $expire | grep -qw not; then
2015-01-29 09:33:35 +01:00
pr_red "expired!"
2014-12-18 09:33:24 +01:00
else
2015-01-30 16:26:55 +01:00
SECS2WARN = ` expr 24 \* 60 \* 60 \* $DAYS2WARN2 ` # low threshold first
2014-12-18 09:33:24 +01:00
expire = ` $OPENSSL x509 -in $HOSTCERT -checkend $SECS2WARN `
if echo " $expire " | grep -qw not; then
SECS2WARN = ` expr 24 \* 60 \* 60 \* $DAYS2WARN2 `
expire = ` $OPENSSL x509 -in $HOSTCERT -checkend $SECS2WARN `
if echo " $expire " | grep -qw not; then
2015-01-29 09:33:35 +01:00
pr_litegreen " >= $DAYS2WARN1 days "
2014-12-18 09:33:24 +01:00
else
2015-01-30 16:26:55 +01:00
pr_brown " expires < $DAYS2WARN1 days "
2014-12-18 09:33:24 +01:00
fi
else
2015-01-30 16:26:55 +01:00
pr_litered " expires < $DAYS2WARN2 days! "
2014-12-18 09:33:24 +01:00
fi
fi
enddate = ` date --date= " $( $OPENSSL x509 -in $HOSTCERT -noout -enddate | cut -d= -f 2) " +"%F %H:%M %z" `
startdate = ` date --date= " $( $OPENSSL x509 -in $HOSTCERT -noout -startdate | cut -d= -f 2) " +"%F %H:%M" `
outln " ( $startdate --> $enddate ) "
2015-02-21 11:47:12 +01:00
savedir = ` pwd ` ; cd $TEMPDIR
$OPENSSL s_client -showcerts $STARTTLS -connect $NODEIP :$PORT $SNI 2>/dev/null </dev/null | \
awk -v c = -1 '/-----BEGIN CERTIFICATE-----/{inc=1;c++} inc {print > ("level" c ".crt")} /---END CERTIFICATE-----/{inc=0}'
nrsaved = ` ls $TEMPDIR /level?.crt | wc -w`
outln " # of certificates provided $nrsaved "
cd $savedir
2014-12-18 09:33:24 +01:00
out " Certificate Revocation List "
crl = ` $OPENSSL x509 -in $HOSTCERT -noout -text | grep -A 4 "CRL Distribution" | grep URI | sed 's/^.*URI://' `
2015-01-29 09:33:35 +01:00
[ x" $crl " = = "x" ] && pr_literedln "--" || echo " $crl "
2014-12-18 09:33:24 +01:00
out " OCSP URI "
ocsp_uri = ` $OPENSSL x509 -in $HOSTCERT -noout -ocsp_uri`
2015-01-29 09:33:35 +01:00
[ x" $ocsp_uri " = = "x" ] && pr_literedln "--" || echo " $ocsp_uri "
2014-12-18 09:33:24 +01:00
out " OCSP stapling "
2014-08-29 14:57:20 +02:00
if grep "OCSP response" $TMPFILE | grep -q "no response sent" ; then
out " not offered"
else
if grep "OCSP Response Status" $TMPFILE | grep -q successful; then
2015-01-29 09:33:35 +01:00
pr_litegreen " OCSP stapling offered"
2014-08-29 14:57:20 +02:00
else
outln " not sure what's going on here, debug:"
grep -A 20 "OCSP response" $TMPFILE
ret = 2
fi
fi
fi
outln
2014-07-01 16:28:16 +02:00
#gmt_unix_time, removed since 1.0.1f
#
#remotetime=`grep -w "Start Time" $TMPFILE | sed 's/[A-Za-z:() ]//g'`
#if [ ! -z "$remotetime" ]; then
# remotetime_stdformat=`date --date="@$remotetime" "+%Y-%m-%d %r"`
# difftime=`expr $localtime - $remotetime`
# [ $difftime -gt 0 ] && difftime="+"$difftime
# difftime=$difftime" s"
2014-07-16 19:04:15 +02:00
# outln " remotetime? : $remotetime ($difftime) = $remotetime_stdformat"
# outln " $remotetime"
# outln " $localtime"
2014-07-01 16:28:16 +02:00
#fi
#http://www.moserware.com/2009/06/first-few-milliseconds-of-https.html
2014-12-19 17:02:26 +01:00
tmpfile_handle tlsextdebug+status.txt
2014-07-01 16:28:16 +02:00
return $ret
}
2015-02-03 23:46:47 +01:00
# FIXME: revoked, see checkcert.sh
# FIXME: Trust (only CN)
2014-07-01 16:28:16 +02:00
# http://www.heise.de/security/artikel/Forward-Secrecy-testen-und-einrichten-1932806.html
pfs( ) {
2014-07-16 19:04:15 +02:00
outln
2015-01-29 09:33:35 +01:00
pr_blue "--> Testing (Perfect) Forward Secrecy (P)FS)" ; outln " -- omitting 3DES, RC4 and Null Encryption here"
2014-07-01 16:28:16 +02:00
# https://community.qualys.com/blogs/securitylabs/2013/08/05/configuring-apache-nginx-and-openssl-for-forward-secrecy
PFSOK = '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'
2014-10-23 15:40:15 +02:00
# ^^^ remark: the exclusing via ! doesn't work with libressl.
#
2014-07-01 16:28:16 +02:00
# PFSOK='EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH'
2014-10-23 15:40:15 +02:00
# this catches also ECDHE-ECDSA-NULL-SHA or ECDHE-RSA-RC4-SHA
2014-07-01 16:28:16 +02:00
2014-11-19 17:08:59 +01:00
$OPENSSL ciphers -V " $PFSOK " >$TMPFILE 2>/dev/null
if [ $? -ne 0 ] ; then
number_pfs = ` wc -l $TMPFILE | awk '{ print $1 }' `
if [ " $number_pfs " -le " $CLIENT_MIN_PFS " ] ; then
outln
2015-01-29 09:33:35 +01:00
pr_magentaln " Local problem: you have only $number_pfs client side PFS ciphers "
2014-11-19 17:08:59 +01:00
outln " Thus it doesn't make sense to test PFS"
[ $number_pfs -ne 0 ] && cat $TMPFILE
return 1
fi
2014-07-01 16:28:16 +02:00
fi
savedciphers = ` cat $TMPFILE `
2014-11-30 01:30:20 +01:00
[ $SHOW_LOC_CIPH = "1" ] && echo "local ciphers available for testing PFS:" && echo ` cat $TMPFILE `
2014-07-01 16:28:16 +02:00
$OPENSSL s_client -cipher 'ECDH:DH' $STARTTLS -connect $NODEIP :$PORT $SNI & >$TMPFILE </dev/null
ret = $?
2014-07-16 19:04:15 +02:00
outln
2014-07-01 16:28:16 +02:00
if [ $ret -ne 0 ] || [ ` grep -c "BEGIN CERTIFICATE" $TMPFILE ` -eq 0 ] ; then
2015-01-29 09:33:35 +01:00
pr_brown "No PFS available"
2014-07-01 16:28:16 +02:00
else
2015-01-29 23:20:58 +01:00
pr_litegreenln "In general PFS is offered. Now testing specific ciphers ..." ;
2015-01-23 12:01:32 +01:00
outln "(it depends on the browser/client whether one of them will be used)\n"
2015-02-07 17:30:36 +01:00
none = 0
2014-07-01 16:28:16 +02:00
neat_header
$OPENSSL ciphers -V " $PFSOK " | 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
ret = $?
if [ $ret -ne 0 ] && [ " $SHOW_EACH_C " -eq 0 ] ; then
continue # no successful connect AND not verbose displaying each cipher
fi
normalize_ciphercode $hexcode
neat_list $HEXC $ciph $kx $enc $strength
if [ " $SHOW_EACH_C " -ne 0 ] ; then
if [ $ret -eq 0 ] ; then
2015-01-29 09:33:35 +01:00
pr_green "works"
2014-07-01 16:28:16 +02:00
else
2014-07-16 19:04:15 +02:00
out "not a/v"
2014-07-01 16:28:16 +02:00
fi
else
2015-02-07 17:30:36 +01:00
none = 1
2014-07-01 16:28:16 +02:00
fi
2014-07-16 19:04:15 +02:00
outln
2014-07-01 16:28:16 +02:00
done
2014-07-16 19:04:15 +02:00
outln
2015-02-07 17:30:36 +01:00
if [ " $none " -eq 0 ] ; then
2014-07-01 16:28:16 +02:00
ret = 0
else
2015-01-29 09:33:35 +01:00
pr_magenta "no PFS ciphers found"
2014-07-01 16:28:16 +02:00
ret = 1
fi
fi
2014-12-19 17:02:26 +01:00
tmpfile_handle $FUNCNAME .txt
2014-07-01 16:28:16 +02:00
return $ret
2015-01-23 12:01:32 +01:00
#FIXME: setopt or something different
2014-07-01 16:28:16 +02:00
}
rc4( ) {
2015-01-23 12:01:32 +01:00
# shopt -s lastpipe # otherwise it's more tricky to access variables in a while loop
2014-07-16 19:04:15 +02:00
outln
2015-01-29 09:33:35 +01:00
pr_blue "--> Checking RC4 Ciphers" ; outln
2014-07-01 16:28:16 +02:00
$OPENSSL ciphers -V 'RC4:@STRENGTH' >$TMPFILE
2014-11-30 01:30:20 +01:00
[ $SHOW_LOC_CIPH = "1" ] && echo "local ciphers available for testing RC4:" && echo ` cat $TMPFILE `
2014-07-01 16:28:16 +02:00
$OPENSSL s_client -cipher ` $OPENSSL ciphers RC4` $STARTTLS -connect $NODEIP :$PORT $SNI & >/dev/null </dev/null
2015-01-20 21:59:21 +01:00
if [ $? -eq 0 ] ; then
2015-01-29 10:46:16 +01:00
pr_literedln "\nRC4 is broken and is offered! Now testing specific ciphers..." ;
2015-01-23 12:01:32 +01:00
outln "(for legacy support e.g. IE6 rather consider x13 or x0a)\n"
2014-07-01 16:28:16 +02:00
bad = 1
neat_header
cat $TMPFILE | 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
ret = $?
if [ $ret -ne 0 ] && [ " $SHOW_EACH_C " -eq 0 ] ; then
continue # no successful connect AND not verbose displaying each cipher
fi
normalize_ciphercode $hexcode
neat_list $HEXC $ciph $kx $enc $strength
if [ " $SHOW_EACH_C " -ne 0 ] ; then
if [ $ret -eq 0 ] ; then
2015-01-29 09:33:35 +01:00
pr_litered "available"
2014-07-01 16:28:16 +02:00
else
2014-11-17 18:49:56 +01:00
out "not a/v"
2014-07-01 16:28:16 +02:00
fi
else
bad = 1
2014-07-16 19:04:15 +02:00
out
2014-07-01 16:28:16 +02:00
fi
2014-07-16 19:04:15 +02:00
outln
2014-07-01 16:28:16 +02:00
done
# https://en.wikipedia.org/wiki/Transport_Layer_Security#RC4_attacks
# http://blog.cryptographyengineering.com/2013/03/attack-of-week-rc4-is-kind-of-broken-in.html
2014-07-16 19:04:15 +02:00
outln
2014-07-01 16:28:16 +02:00
else
2014-07-16 19:04:15 +02:00
outln
2015-01-29 09:33:35 +01:00
pr_litegreenln "no RC4 ciphers detected (OK)"
2014-07-01 16:28:16 +02:00
bad = 0
fi
2015-01-23 12:01:32 +01:00
# shopt -u lastpipe # othwise for some reason it segfaults
2015-01-21 12:53:00 +01:00
# FIXME: still segfaults: see https://www.mail-archive.com/bug-bash@gnu.org/msg14428.html |
# maybe use @PIPESTATUS as a workaround
2014-12-19 17:02:26 +01:00
tmpfile_handle $FUNCNAME .txt
2014-07-01 16:28:16 +02:00
return $bad
}
# good source for configuration and bugs: https://wiki.mozilla.org/Security/Server_Side_TLS
# good start to read: http://en.wikipedia.org/wiki/Transport_Layer_Security#Attacks_against_TLS.2FSSL
lucky13( ) {
#FIXME: to do
# CVE-2013-0169
# in a nutshell: don't offer CBC suites (again). MAC as a fix for padding oracles is not enough
# best: TLS v1.2+ AES GCM
echo "FIXME"
echo
}
2014-12-21 23:22:50 +01:00
spdy_pre( ) {
2014-07-01 16:28:16 +02:00
if [ " x $STARTTLS " != "x" ] ; then
2015-02-04 09:48:34 +01:00
[ [ $DEBUG -ge 2 ] ] && outln "SPDY doesn't work with !HTTP"
2014-12-21 23:22:50 +01:00
return 1
2014-07-01 16:28:16 +02:00
fi
2014-07-16 19:04:15 +02:00
# first, does the current openssl support it?
2014-07-01 16:28:16 +02:00
$OPENSSL s_client help 2>& 1 | grep -qw nextprotoneg
if [ $? -ne 0 ] ; then
2015-01-29 09:33:35 +01:00
pr_magenta " Local problem: $OPENSSL doesn't support SPDY " ; outln
2014-12-21 23:22:50 +01:00
return 7
2014-07-01 16:28:16 +02:00
fi
2014-12-21 23:22:50 +01:00
return 0
}
spdy( ) {
out " SPDY/NPN "
spdy_pre || return 0
2014-07-01 16:28:16 +02:00
$OPENSSL s_client -host $NODE -port $PORT -nextprotoneg $NPN_PROTOs </dev/null 2>/dev/null >$TMPFILE
if [ $? -eq 0 ] ; then
# we need -a here
2014-07-16 19:04:15 +02:00
tmpstr = ` grep -a '^Protocols' $TMPFILE | sed 's/Protocols.*: //' `
if [ -z " $tmpstr " -o " $tmpstr " = " " ] ; then
out "not offered"
2014-07-01 16:28:16 +02:00
ret = 1
else
# now comes a strange thing: "Protocols advertised by server:" is empty but connection succeeded
if echo $tmpstr | egrep -q "spdy|http" ; then
2015-01-29 09:33:35 +01:00
pr_bold " $tmpstr " ; out " (advertised)"
2014-07-01 16:28:16 +02:00
ret = 0
else
2015-01-29 09:33:35 +01:00
pr_litemagenta "please check manually, response from server was ambigious ..."
2014-07-01 16:28:16 +02:00
ret = 10
fi
fi
else
2015-01-29 09:33:35 +01:00
pr_litemagenta "handshake failed"
2014-07-01 16:28:16 +02:00
ret = 2
fi
2014-07-16 19:04:15 +02:00
outln
2014-07-01 16:28:16 +02:00
# btw: nmap can do that too http://nmap.org/nsedoc/scripts/tls-nextprotoneg.html
# nmap --script=tls-nextprotoneg #NODE -p $PORT is your friend if your openssl doesn't want to test this
2014-12-19 17:02:26 +01:00
tmpfile_handle $FUNCNAME .txt
2014-07-01 16:28:16 +02:00
return $ret
}
fd_socket( ) {
# arg doesn't work here
if ! exec 5<> /dev/tcp/$NODEIP /$PORT ; then
2015-01-29 09:33:35 +01:00
pr_magenta " `basename $0 `: unable to open a socket to $NODEIP : $PORT "
2014-07-01 16:28:16 +02:00
return 6
fi
return 0
}
2014-10-07 12:04:21 +02:00
close_socket( ) {
exec 5<& -
exec 5>& -
return 0
}
2015-01-29 10:46:16 +01:00
## 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
}
2015-02-04 09:48:34 +01:00
# arg1: name of file with socket reply
2015-01-29 10:46:16 +01:00
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
}
2015-02-04 09:48:34 +01:00
# arg1: name of file with socket reply
display_tls_serverhello( ) {
# server hello:
# byte 0: 0x16=TLS, 0x15= TLS alert
# byte 1+2: 03, TLS version
# byte 3+4: length all
# byte 5: handshake type (2=hello) TLS alert: level (2=fatal), descr (0x28=handshake failure)
# byte 6+7+8: length server hello
# byte 9+10: 03, TLS version (00: SSLv3, 01: TLS 1.0, 02: TLS 1.1, 03: TLS 1.2)
# byte 11-14: TLS timestamp
# byte 15-42: random (28 bytes)
# byte 43 : session id length
# byte 44+45+sid-len: cipher suite!
# byte 46+sid-len: compression method: 00: none, 01: deflate
# byte 47+48+sid-len: extension length
tls_hello_ascii = ` hexdump -v -e '16/1 "%02X"' $1 `
[ [ " $DEBUG " -eq 5 ] ] && echo $tls_hello_ascii # one line without any blanks
[ [ -z $tls_hello_ascii ] ] && return 0 # no server hello received
# now scrape two bytes out of the reply per byte
tls_hello_initbyte = " ${ tls_hello_ascii : 0 : 2 } " # normally this is x16
tls_hello_protocol = " ${ tls_hello_ascii : 2 : 4 } "
tls_len_all = ` printf "%d\n" ${ tls_hello_ascii : 6 : 4 } `
if [ [ $tls_hello_initbyte != "16" ] ] ; then
[ [ $DEBUG -ge 1 ] ] && echo " tls_hello_initbyte: 0x $tls_hello_initbyte "
if [ [ $DEBUG -ge 2 ] ] ; then
echo " tls_hello_protocol: 0x $tls_hello_protocol "
echo " tls_len_all: $tls_len_all "
echo " tls_err_level: ${ tls_hello_ascii : 10 : 2 } "
echo " tls_err_descr: 0x ${ tls_hello_ascii : 12 : 2 } "
fi
return 1
fi
DETECTED_TLS_VERSION = $tls_hello_protocol
tls_hello = " ${ tls_hello_ascii : 10 : 2 } " # normally this is x02
tls_hello_protocol2 = " ${ tls_hello_ascii : 18 : 4 } "
tls_hello_time = " ${ tls_hello_ascii : 22 : 8 } "
tls_time = ` printf "%d\n" 0x$tls_hello_time `
tls_time = ` date --date= " @ $tls_time " "+%Y-%m-%d %r" `
tls_sid_len = ` printf "%d\n" 0x${ tls_hello_ascii : 86 : 2 } `
let sid_offset = 88+$tls_sid_len *2
tls_cipher_suite = " ${ tls_hello_ascii : $sid_offset : 4 } "
let sid_offset = 92+$tls_sid_len *2
tls_compression_method = " ${ tls_hello_ascii : $sid_offset : 2 } "
if [ [ $DEBUG -ge 2 ] ] ; then
echo " tls_hello_initbyte: 0x $tls_hello_initbyte "
echo " tls_hello: 0x $tls_hello "
echo " tls_hello_protocol: 0x $tls_hello_protocol "
if [ [ $DEBUG -ge 4 ] ] ; then
echo " tls_hello_protocol2: 0x $tls_hello_protocol2 "
echo " tls_len_all: $tls_len_all "
echo " tls_sid_len: $tls_sid_len "
fi
echo " tls_hello_time: 0x $tls_hello_time ( $tls_time ) "
echo " tls_cipher_suite: 0x $tls_cipher_suite "
echo " tls_compression_method: 0x $tls_compression_method "
fi
return 0
}
2015-01-29 10:46:16 +01:00
# 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' `
}
2015-02-04 09:48:34 +01:00
len2twobytes( ) {
len_arg1 = ` echo ${# 1 } `
[ [ $len_arg1 -le 2 ] ] && LEN_STR = ` printf "00, %02s \n" $1 `
[ [ $len_arg1 -eq 3 ] ] && LEN_STR = ` printf "%02s, %02s \n" ${ 1 : 0 : 1 } ${ 1 : 1 : 2 } `
[ [ $len_arg1 -eq 4 ] ] && LEN_STR = ` printf "%02s, %02s \n" ${ 1 : 0 : 2 } ${ 1 : 2 : 2 } `
}
2015-01-29 10:46:16 +01:00
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
}
2015-02-04 09:48:34 +01:00
#for tls_low_byte in "00" "01" "02" "03"; do
tls_sockets( ) {
SN_HEX = ""
LEN_SN_HEX = 0
COL_WIDTH = 32
USLEEP_REC = ${ USLEEP_REC :- 0 .2 }
USLEEP_SND = ${ USLEEP_SND :- 0 .1 } # 1 second wait until otherwise specified
MAX_WAITSOCK = 2
SOCK_REPLY_FILE = ""
NW_STR = ""
LEN_STR = ""
DETECTED_TLS_VERSION = ""
# 133 cipher: spdy, TLS 1.2
TLS12_CIPHER = "
cc, 14, cc, 13, cc, 15, c0, 30, c0, 2c, c0, 28, c0, 24, c0, 14,
c0, 0a, c0, 22, c0, 21, c0, 20, 00, a5, 00, a3, 00, a1, 00, 9f,
00, 6b, 00, 6a, 00, 69, 00, 68, 00, 39, 00, 38, 00, 37, 00, 36,
c0, 77, c0, 73, 00, c4, 00, c3, 00, c2, 00, c1, 00, 88, 00, 87,
00, 86, 00, 85, c0, 32, c0, 2e, c0, 2a, c0, 26, c0, 0f, c0, 05,
c0, 79, c0, 75, 00, 9d, 00, 3d, 00, 35, 00, c0, 00, 84, c0, 2f,
c0, 2b, c0, 27, c0, 23, c0, 13, c0, 09, c0, 1f, c0, 1e, c0, 1d,
00, a4, 00, a2, 00, a0, 00, 9e, 00, 67, 00, 40, 00, 3f, 00, 3e,
00, 33, 00, 32, 00, 31, 00, 30, c0, 76, c0, 72, 00, be, 00, bd,
00, bc, 00, bb, 00, 9a, 00, 99, 00, 98, 00, 97, 00, 45, 00, 44,
00, 43, 00, 42, c0, 31, c0, 2d, c0, 29, c0, 25, c0, 0e, c0, 04,
c0, 78, c0, 74, 00, 9c, 00, 3c, 00, 2f, 00, ba, 00, 96, 00, 41,
00, 07, c0, 11, c0, 07, 00, 66, c0, 0c, c0, 02, 00, 05, 00, 04,
c0, 12, c0, 08, c0, 1c, c0, 1b, c0, 1a, 00, 16, 00, 13, 00, 10,
00, 0d, c0, 0d, c0, 03, 00, 0a, 00, 63, 00, 15, 00, 12, 00, 0f,
00, 0c, 00, 62, 00, 09, 00, 65, 00, 64, 00, 14, 00, 11, 00, 0e,
00, 0b, 00, 08, 00, 06, 00, 03, 00, ff"
# 76 cipher for SSLv3, TLS 1, TLS 1.1:
TLS_CIPHER = "
c0, 14, c0, 0a, c0, 22, c0, 21, c0, 20, 00, 39, 00, 38, 00, 37,
00, 36, 00, 88, 00, 87, 00, 86, 00, 85, c0, 0f, c0, 05, 00, 35,
00, 84, c0, 13, c0, 09, c0, 1f, c0, 1e, c0, 1d, 00, 33, 00, 32,
00, 31, 00, 30, 00, 9a, 00, 99, 00, 98, 00, 97, 00, 45, 00, 44,
00, 43, 00, 42, c0, 0e, c0, 04, 00, 2f, 00, 96, 00, 41, 00, 07,
c0, 11, c0, 07, 00, 66, c0, 0c, c0, 02, 00, 05, 00, 04, c0, 12,
c0, 08, c0, 1c, c0, 1b, c0, 1a, 00, 16, 00, 13, 00, 10, 00, 0d,
c0, 0d, c0, 03, 00, 0a, 00, 63, 00, 15, 00, 12, 00, 0f, 00, 0c,
00, 62, 00, 09, 00, 65, 00, 64, 00, 14, 00, 11, 00, 0e, 00, 0b,
00, 08, 00, 06, 00, 03, 00, ff"
#formatted example for SNI
#00 00 # extention server_name
#00 1a # length = the following +2 = server_name length + 5
#00 18 # server_name list_length = server_name length +3
#00 # server_name type (hostname)
#00 15 # server_name length
#66 66 66 66 66 66 2e 66 66 66 66 66 66 66 66 66 66 2e 66 66 66 target.mydomain1.tld # server_name target
# arg1: TLS_VER_LSB
# arg2: CIPHER_SUITES string
# arg3: SERVERNAME
# ??? more extensions?
len_sni = ` echo ${# 3 } `
#tls_ver=printf "%02x\n" $1"
code2network " $2 "
cipher_suites = " $NW_STR " # we don't have the leading \x here so string length is two byte less, see next
# convert length's from dec to hex:
hex_len_sn_hex = ` printf "%02x\n" $LEN_SN_HEX `
hex_len_sn_hex3 = ` printf "%02x\n" $(( LEN_SN_HEX+3)) `
hex_len_sn_hex5 = ` printf "%02x\n" $(( LEN_SN_HEX+5)) `
hex_len_extention = ` printf "%02x\n" $(( LEN_SN_HEX+9)) `
len_ciph_suites_byte = ` echo ${# cipher_suites } `
let "len_ciph_suites_byte += 2"
# we have additional 2 chars \x in each 2 byte string and 2 byte ciphers, so we need to divide by 4:
len_ciph_suites = ` printf "%02x\n" $(( $len_ciph_suites_byte / 4 )) `
len2twobytes " $len_ciph_suites "
len_ciph_suites_word = " $LEN_STR "
[ [ $DEBUG -ge 4 ] ] && echo $len_ciph_suites_word
len2twobytes ` printf "%02x\n" $(( 0 x$len_ciph_suites + 0 x27 + 0 x$hex_len_extention + 0 x2)) `
#len2twobytes `printf "%02x\n" $((0x$len_ciph_suites + 0x27))`
len_c_hello_word = " $LEN_STR "
[ [ $DEBUG -ge 4 ] ] && echo $len_c_hello_word
len2twobytes ` printf "%02x\n" $(( 0 x$len_ciph_suites + 0 x2b + 0 x$hex_len_extention + 0 x2)) `
#len2twobytes `printf "%02x\n" $((0x$len_ciph_suites + 0x2b))`
len_all_word = " $LEN_STR "
[ [ $DEBUG -ge 4 ] ] && echo $len_all_word
TLS_CLIENT_HELLO = "
# TLS header ( 5 bytes)
,16, 03, $1 # TLS Version
,$len_all_word # Length <---
# Handshake header:
,01 # Type (x01 for ClientHello)
,00, $len_c_hello_word # Length ClientHello
,03, $1 # TLS Version (again)
,54, 51, 1e, 7a # Unix time since see www.moserware.com/2009/06/first-few-milliseconds-of-https.html
,de, ad, be, ef # Random 28 bytes
,31, 33, 07, 00, 00, 00, 00, 00
,cf, bd, 39, 04, cc, 16, 0a, 85
,03, 90, 9f, 77, 04, 33, d4, de
,00 # Session ID length
,$len_ciph_suites_word # Cipher suites length
# Cipher suites
,$cipher_suites
,01 # Compression methods length
,00" # Compression method (x00 for NULL)
EXTENSION_CONTAINING_SNI = "
,00, $hex_len_extention # first the len of all (here: 1) extentions. We assume len(hostname) < FF - 9
,00, 00 # extention server_name
,00, $hex_len_sn_hex5 # length SNI EXT
,00, $hex_len_sn_hex3 # server_name list_length
,00 # server_name type (hostname)
,00, $hex_len_sn_hex # server_name length
,$SN_HEX " # server_name target
fd_socket 5 || return 6
code2network " $TLS_CLIENT_HELLO $EXTENSION_CONTAINING_SNI "
#code2network "$TLS_CLIENT_HELLO"
data = ` echo $NW_STR `
[ [ " $DEBUG " -ge 2 ] ] && printf "sending client hello..."
if [ [ " $tls_low_byte " = = "03" ] ] ; then
socksend_clienthello $tls_low_byte " $TLS12_CIPHER " $SNIHEX
else
socksend_clienthello $tls_low_byte " $TLS_CIPHER " $SNIHEX
fi
sockread_serverhello 32768 0
[ [ " $DEBUG " -ge 2 ] ] && printf "reading server hello..."
if [ [ " $DEBUG " -ge 3 ] ] ; then
hexdump -C $SOCK_REPLY_FILE | head -6
echo
fi
display_tls_serverhello " $SOCK_REPLY_FILE "
ret = $?
# 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 " (returned $lines lines) "
# case $tls_low_byte in
# 00) tls_str="SSLv3" ;;
# 01) tls_str="TLS 1" ;;
# 02) tls_str="TLS 1.1" ;;
# 03) tls_str="TLS 1.2" ;;
# esac
# printf "Protokoll "; tput bold; printf "$tls_low_byte = $tls_str"; tput sgr0; printf ": "
if [ [ $ret -eq 1 ] ] || [ [ $lines -eq 1 ] ] ; then
outln "NOT available"
ret = 1
else
if [ [ 03$tls_low_byte -eq $DETECTED_TLS_VERSION ] ] ; then
outln "available"
ret = 0
else
out "NOT available "
[ [ $DEBUG -ge 2 ] ] && echo -n " send: 0x03 $tls_low_byte , returned: 0x $DETECTED_TLS_VERSION "
echo
fi
fi
close_socket
TMPFILE = $SOCK_REPLY_FILE
tmpfile_handle $FUNCNAME .dd
return $ret
}
2015-01-29 10:46:16 +01:00
2014-07-01 16:28:16 +02:00
ok_ids( ) {
2015-01-29 10:46:16 +01:00
greenln "\n ok -- something resetted our ccs packets"
2015-01-20 21:59:21 +01:00
return 0
2014-07-01 16:28:16 +02:00
}
2014-11-27 21:33:33 +01:00
2014-07-01 16:28:16 +02:00
ccs_injection( ) {
# see https://www.openssl.org/news/secadv_20140605.txt
# mainly adapted from Ramon de C Valle's C code from https://gist.github.com/rcvalle/71f4b027d61a78c42607
2015-01-29 09:33:35 +01:00
pr_bold " CCS " ; out " (CVE-2014-0224), experimental "
2014-07-01 16:28:16 +02:00
$OPENSSL s_client $STARTTLS -connect $NODEIP :$PORT & >$TMPFILE </dev/null
2014-11-27 21:33:33 +01:00
tls_proto_offered = ` grep -w Protocol $TMPFILE | sed -E 's/[^[:digit:]]//g' `
#tls_proto_offered=`grep -w Protocol $TMPFILE | sed 's/^.*Protocol//'`
2014-07-01 16:28:16 +02:00
case $tls_proto_offered in
2014-11-27 21:33:33 +01:00
12) tls_hexcode = "x03, x03" ; ;
11) tls_hexcode = "x03, x02" ; ;
*) tls_hexcode = "x03, x01" ; ;
2014-07-01 16:28:16 +02:00
esac
2014-11-27 21:33:33 +01:00
ccs_message = " , x14, $tls_hexcode ,x00, x01, x01 "
2014-07-01 16:28:16 +02:00
client_hello = "
2014-11-27 21:33:33 +01:00
# TLS header (5 bytes)
,x16, # content type (x16 for handshake)
$tls_hexcode , # TLS version
x00, x93, # length
2014-07-01 16:28:16 +02:00
# Handshake header
2014-11-27 21:33:33 +01:00
x01, # type (x01 for ClientHello)
x00, x00, x8f, # length
$tls_hexcode , # TLS version
2014-07-01 16:28:16 +02:00
# Random (32 byte)
x53, x43, x5b, x90, x9d, x9b, x72, x0b,
xbc, x0c, xbc, x2b, x92, xa8, x48, x97,
xcf, xbd, x39, x04, xcc, x16, x0a, x85,
x03, x90, x9f, x77, x04, x33, xd4, xde,
2014-11-27 21:33:33 +01:00
x00, # session ID length
x00, x68, # cipher suites length
2014-07-01 16:28:16 +02:00
# Cipher suites (51 suites)
xc0, x13, xc0, x12, xc0, x11, xc0, x10,
xc0, x0f, xc0, x0e, xc0, x0d, xc0, x0c,
xc0, x0b, xc0, x0a, xc0, x09, xc0, x08,
xc0, x07, xc0, x06, xc0, x05, xc0, x04,
xc0, x03, xc0, x02, xc0, x01, x00, x39,
x00, x38, x00, x37, x00, x36, x00, x35, x00, x34,
x00, x33, x00, x32, x00, x31, x00, x30,
x00, x2f, x00, x16, x00, x15, x00, x14,
x00, x13, x00, x12, x00, x11, x00, x10,
x00, x0f, x00, x0e, x00, x0d, x00, x0c,
x00, x0b, x00, x0a, x00, x09, x00, x08,
x00, x07, x00, x06, x00, x05, x00, x04,
x00, x03, x00, x02, x00, x01, x01, x00"
fd_socket 5 || return 6
2015-01-21 12:53:00 +01:00
[ [ $DEBUG -ge 2 ] ] && out "\nsending client hello, "
2014-11-27 21:33:33 +01:00
socksend " $client_hello " 1
2014-11-18 00:26:58 +01:00
sockread 16384
2014-07-01 16:28:16 +02:00
2015-01-21 12:53:00 +01:00
[ [ $DEBUG -ge 2 ] ] && outln "\nreading server hello"
if [ [ $DEBUG -ge 3 ] ] ; then
2014-11-19 13:22:22 +01:00
echo " $SOCKREPLY " | " ${ HEXDUMPVIEW [@] } " | head -20
2014-07-16 19:04:15 +02:00
outln "[...]"
2014-11-18 00:26:58 +01:00
outln " \npayload #1 with TLS version $tls_hexcode : "
2014-07-01 16:28:16 +02:00
fi
2014-11-27 21:33:33 +01:00
socksend " $ccs_message " 1 || ok_ids
sockread 2048 5 # 5 seconds
2015-01-21 12:53:00 +01:00
if [ [ $DEBUG -ge 3 ] ] ; then
2014-11-18 00:26:58 +01:00
outln "\n1st reply: "
2014-11-19 13:22:22 +01:00
out " $SOCKREPLY " | " ${ HEXDUMPVIEW [@] } " | head -20
2014-11-18 00:26:58 +01:00
# ok: 15 | 0301 | 02 | 02 0a == ALERT | TLS 1.0 | Length=2 | Unexpected Message (0a)
outln
outln " payload #2 with TLS version $tls_hexcode : "
fi
2014-11-27 21:33:33 +01:00
socksend " $ccs_message " 2 || ok_ids
2014-11-18 00:26:58 +01:00
sockread 2048 5
2014-09-16 22:18:09 +02:00
retval = $?
2014-07-01 16:28:16 +02:00
2015-01-21 12:53:00 +01:00
if [ [ $DEBUG -ge 3 ] ] ; then
2014-11-18 00:26:58 +01:00
outln "\n2nd reply: "
2014-11-19 13:22:22 +01:00
out " $SOCKREPLY " | " ${ HEXDUMPVIEW [@] } "
2014-11-18 00:26:58 +01:00
# not ok: 15 | 0301 | 02 | 02 | 15 == ALERT | TLS 1.0 | Length=2 | Decryption failed (21)
# ok: 0a or nothing: ==> RST
2014-07-16 19:04:15 +02:00
outln
2014-07-01 16:28:16 +02:00
fi
2014-11-19 13:22:22 +01:00
reply_sanitized = ` echo " $SOCKREPLY " | " ${ HEXDUMPPLAIN [@] } " | sed 's/^..........//' `
lines = ` echo " $SOCKREPLY " | " ${ HEXDUMP [@] } " | wc -l`
2014-07-01 16:28:16 +02:00
if [ " $reply_sanitized " = = "0a" ] || [ " $lines " -gt 1 ] ; then
2015-01-29 09:33:35 +01:00
pr_green "not vulnerable (OK)"
2015-01-29 10:46:16 +01:00
ret = 0
2014-07-01 16:28:16 +02:00
else
2015-02-21 11:47:12 +01:00
pr_red "VULNERABLE (not OK)"
2014-07-01 16:28:16 +02:00
ret = 1
fi
2014-11-20 10:46:55 +01:00
[ $retval -eq 3 ] && out "(timed out)"
2014-09-16 22:18:09 +02:00
outln
2014-10-07 12:04:21 +02:00
close_socket
2014-12-19 17:02:26 +01:00
tmpfile_handle $FUNCNAME .txt
2014-07-01 16:28:16 +02:00
return $ret
}
heartbleed( ) {
2015-01-29 09:33:35 +01:00
pr_bold " Heartbleed\c" ; out " (CVE-2014-0160) "
2014-11-19 13:22:22 +01:00
# mainly adapted from https://gist.github.com/takeshixx/10107280
2014-07-01 16:28:16 +02:00
2014-11-20 10:46:55 +01:00
# determine TLS versions available:
$OPENSSL s_client $STARTTLS -connect $NODEIP :$PORT -tlsextdebug & >$TMPFILE </dev/null
2014-11-27 21:33:33 +01:00
tls_proto_offered = ` grep -w Protocol $TMPFILE | sed -E 's/[^[:digit:]]//g' `
2014-11-19 13:22:22 +01:00
case $tls_proto_offered in
2014-11-27 21:33:33 +01:00
12) tls_hexcode = "x03, x03" ; ;
11) tls_hexcode = "x03, x02" ; ;
*) tls_hexcode = "x03, x01" ; ;
2014-11-19 13:22:22 +01:00
esac
2014-11-27 21:33:33 +01:00
heartbleed_payload = " , x18, $tls_hexcode , x00, x03, x01, x40, x00 "
2014-07-01 16:28:16 +02:00
2014-11-19 13:22:22 +01:00
client_hello = "
# TLS header ( 5 bytes)
2014-11-27 21:33:33 +01:00
,x16, # content type (x16 for handshake)
$tls_hexcode , # TLS version
x00, xdc, # length
2014-11-19 13:22:22 +01:00
# Handshake header
2014-11-27 21:33:33 +01:00
x01, # type (x01 for ClientHello)
x00, x00, xd8, # length
$tls_hexcode , # TLS version
2014-11-19 13:22:22 +01:00
# Random (32 byte)
x53, x43, x5b, x90, x9d, x9b, x72, x0b,
xbc, x0c, xbc, x2b, x92, xa8, x48, x97,
xcf, xbd, x39, x04, xcc, x16, x0a, x85,
x03, x90, x9f, x77, x04, x33, xd4, xde,
2014-11-27 21:33:33 +01:00
x00, # session ID length
x00, x66, # cipher suites length
# cipher suites (51 suites)
2014-11-19 13:22:22 +01:00
xc0, x14, xc0, x0a, xc0, x22, xc0, x21,
x00, x39, x00, x38, x00, x88, x00, x87,
xc0, x0f, xc0, x05, x00, x35, x00, x84,
xc0, x12, xc0, x08, xc0, x1c, xc0, x1b,
x00, x16, x00, x13, xc0, x0d, xc0, x03,
x00, x0a, xc0, x13, xc0, x09, xc0, x1f,
xc0, x1e, x00, x33, x00, x32, x00, x9a,
x00, x99, x00, x45, x00, x44, xc0, x0e,
xc0, x04, x00, x2f, x00, x96, x00, x41,
xc0, x11, xc0, x07, xc0, x0c, xc0, x02,
x00, x05, x00, x04, x00, x15, x00, x12,
x00, x09, x00, x14, x00, x11, x00, x08,
x00, x06, x00, x03, x00, xff,
2014-11-27 21:33:33 +01:00
x01, # compression methods length
x00, # compression method (x00 for NULL)
x00, x49, # extensions length
# extension: ec_point_formats
2014-11-19 13:22:22 +01:00
x00, x0b, x00, x04, x03, x00, x01, x02,
2014-11-27 21:33:33 +01:00
# extension: elliptic_curves
2014-11-19 13:22:22 +01:00
x00, x0a, x00, x34, x00, x32, x00, x0e,
x00, x0d, x00, x19, x00, x0b, x00, x0c,
x00, x18, x00, x09, x00, x0a, x00, x16,
x00, x17, x00, x08, x00, x06, x00, x07,
x00, x14, x00, x15, x00, x04, x00, x05,
x00, x12, x00, x13, x00, x01, x00, x02,
x00, x03, x00, x0f, x00, x10, x00, x11,
2014-11-27 21:33:33 +01:00
# extension: session ticket TLS
2014-11-19 13:22:22 +01:00
x00, x23, x00, x00,
2014-11-27 21:33:33 +01:00
# extension: heartbeat
2014-11-19 13:22:22 +01:00
x00, x0f, x00, x01, x01"
fd_socket 5 || return 6
2015-02-09 14:02:02 +01:00
[ [ $DEBUG -ge 2 ] ] && outln " \nsending client hello (TLS version $tls_hexcode ) "
2014-11-27 21:33:33 +01:00
socksend " $client_hello " 1
2014-11-19 13:22:22 +01:00
sockread 16384
2015-01-21 12:53:00 +01:00
[ [ $DEBUG -ge 2 ] ] && outln "\nreading server hello"
if [ [ $DEBUG -ge 3 ] ] ; then
2014-11-19 13:22:22 +01:00
echo " $SOCKREPLY " | " ${ HEXDUMPVIEW [@] } " | head -20
outln "[...]"
2014-11-27 21:33:33 +01:00
outln " \nsending payload with TLS version $tls_hexcode : "
2014-11-19 13:22:22 +01:00
fi
2014-11-27 21:33:33 +01:00
socksend " $heartbleed_payload " 1
2014-11-19 13:22:22 +01:00
sockread 16384
retval = $?
2015-01-21 12:53:00 +01:00
if [ [ $DEBUG -ge 3 ] ] ; then
2014-11-27 21:33:33 +01:00
outln "\nheartbleed reply: "
2014-11-19 13:22:22 +01:00
echo " $SOCKREPLY " | " ${ HEXDUMPVIEW [@] } "
outln
2014-07-01 16:28:16 +02:00
fi
2014-10-07 12:04:21 +02:00
2014-11-19 13:22:22 +01:00
lines_returned = ` echo " $SOCKREPLY " | " ${ HEXDUMP [@] } " | wc -l`
if [ $lines_returned -gt 1 ] ; then
2015-01-29 09:33:35 +01:00
pr_red "VULNERABLE"
2014-11-19 13:22:22 +01:00
ret = 1
else
2015-01-29 09:33:35 +01:00
pr_green "not vulnerable (OK)"
2014-11-19 13:22:22 +01:00
ret = 0
fi
2014-11-20 10:46:55 +01:00
[ $retval -eq 3 ] && out "(timed out)"
2014-11-19 13:22:22 +01:00
outln
2014-10-07 12:04:21 +02:00
close_socket
2014-12-19 17:02:26 +01:00
tmpfile_handle $FUNCNAME .txt
2014-07-01 16:28:16 +02:00
return $ret
}
2015-02-11 09:43:04 +01:00
# This tests for CVE-2009-3555 / RFC5746, OSVDB: 59968-59974
2014-07-01 16:28:16 +02:00
renego( ) {
ADDCMD = ""
case " $OSSL_VER " in
2014-11-18 20:23:17 +01:00
0.9.8*) # we need this for Mac OSX unfortunately
2014-07-01 16:28:16 +02:00
case " $OSSL_VER_APPENDIX " in
[ a-l] )
2015-01-29 09:33:35 +01:00
pr_magenta " Your $OPENSSL $OSSL_VER cannot test the secure renegotiation vulnerability "
2014-07-01 16:28:16 +02:00
return 3 ; ;
[ m-z] )
# all ok ;;
esac ; ;
2015-02-11 09:43:04 +01:00
1.0.1*| 1.0.2*)
2014-07-01 16:28:16 +02:00
ADDCMD = "-legacy_renegotiation" ; ;
0.9.9*| 1.0*)
# all ok ;;
esac
2015-02-11 09:43:04 +01:00
pr_bold " Secure Client-Initiated Renegotiation " # RFC 5746, community.qualys.com/blogs/securitylabs/2011/10/31/tls-renegotiation-and-denial-of-service-attacks
echo R | $OPENSSL s_client $ADDCMD $STARTTLS -connect $NODEIP :$PORT $SNI & >$TMPFILE
reneg_ok = $? # 0=client is renegotiating and does not get an error: vuln to DoS via client initiated renegotiation
case $reneg_ok in
2015-02-21 11:47:12 +01:00
0) pr_litered "VULNERABLE (NOT ok)" ; outln ", DoS threat" ; ;
2015-02-11 09:43:04 +01:00
1) pr_litegreenln "not vulnerable (OK)" ; ;
*) outln " FIXME: $reneg_ok " ; ;
esac
2015-01-29 09:33:35 +01:00
pr_bold " Renegotiation " ; out "(CVE 2009-3555) "
2014-07-01 16:28:16 +02:00
NEG_STR = "Secure Renegotiation IS NOT"
2014-07-16 19:04:15 +02:00
echo "R" | $OPENSSL s_client $STARTTLS -connect $NODEIP :$PORT $SNI 2>& 1 | grep -iq " $NEG_STR "
2014-07-01 16:28:16 +02:00
secreg = $? # 0= Secure Renegotiation IS NOT supported
2015-02-11 09:43:04 +01:00
case $secreg in
2015-02-21 11:47:12 +01:00
0) pr_redln "VULNERABLE (NOT ok)" ; ;
2015-02-11 09:43:04 +01:00
1) pr_greenln "not vulnerable (OK)" ; ;
*) outln " FIXME: $secreg " ; ;
esac
2014-07-01 16:28:16 +02:00
2015-02-11 09:43:04 +01:00
tmpfile_handle $FUNCNAME .txt
return $secreg
# https://community.qualys.com/blogs/securitylabs/2009/11/05/ssl-and-tls-authentication-gap-vulnerability-discovered
2014-07-01 16:28:16 +02:00
}
crime( ) {
2014-07-16 19:04:15 +02:00
# in a nutshell: don't offer TLS/SPDY compression on the server side
2014-07-01 16:28:16 +02:00
#
# This tests for CRIME Vulnerability (www.ekoparty.org/2012/juliano-rizzo.php) on HTTPS, not SPDY (yet)
# Please note that it is an attack where you need client side control, so in regular situations this
# means anyway "game over", w/wo CRIME
# www.h-online.com/security/news/item/Vulnerability-in-SSL-encryption-is-barely-exploitable-1708604.html
2014-11-30 01:30:20 +01:00
#
2014-07-01 16:28:16 +02:00
ADDCMD = ""
case " $OSSL_VER " in
# =< 0.9.7 was weeded out before
0.9.8)
ADDCMD = "-no_ssl2" ; ;
0.9.9*| 1.0*)
; ;
esac
2015-01-29 09:33:35 +01:00
pr_bold " CRIME, TLS " ; out "(CVE-2012-4929) "
2014-07-01 16:28:16 +02:00
# first we need to test whether OpenSSL binary has zlib support
$OPENSSL zlib -e -a -in /dev/stdin & >/dev/stdout </dev/null | grep -q zlib
if [ $? -eq 0 ] ; then
2015-01-29 09:33:35 +01:00
pr_magentaln " Local Problem: Your $OPENSSL lacks zlib support "
2015-02-11 09:43:04 +01:00
return 7
2014-07-01 16:28:16 +02:00
fi
2015-02-11 09:43:04 +01:00
#STR=`$OPENSSL s_client $ADDCMD $STARTTLS -connect $NODEIP:$PORT $SNI 2>&1 </dev/null | grep Compression `
2015-02-12 13:40:53 +01:00
$OPENSSL s_client $ADDCMD $STARTTLS -connect $NODEIP :$PORT $SNI </dev/null & >$TMPFILE
if grep Compression $TMPFILE | grep -q NONE >/dev/null; then
2015-01-29 09:33:35 +01:00
pr_green "not vulnerable (OK)"
2014-11-30 01:30:20 +01:00
[ [ $SERVICE = = "HTTP" ] ] || out " (not using HTTP anyway)"
2014-07-01 16:28:16 +02:00
ret = 0
else
2014-11-30 01:30:20 +01:00
if [ [ $SERVICE = = "HTTP" ] ] ; then
2015-02-21 11:47:12 +01:00
pr_red "VULNERABLE (NOT ok)"
2014-11-30 01:30:20 +01:00
else
2015-02-21 11:47:12 +01:00
pr_brown "VULNERABLE (NOT ok), but not using HTTP: probably no exploit known"
2014-11-30 01:30:20 +01:00
fi
2014-07-01 16:28:16 +02:00
ret = 1
fi
2014-11-30 01:30:20 +01:00
# not clear whether this is a protocol != HTTP as one needs to have the ability to modify the
# compression input which is done via javascript in the context of HTTP
outln
2014-07-01 16:28:16 +02:00
# this needs to be re-done i order to remove the redundant check for spdy
# weed out starttls, spdy-crime is a web thingy
# if [ "x$STARTTLS" != "x" ]; then
# echo
# return $ret
# fi
# weed out non-webports, spdy-crime is a web thingy. there's a catch thoug, you see it?
# case $PORT in
# 25|465|587|80|110|143|993|995|21)
# echo
# return $ret
# esac
# $OPENSSL s_client help 2>&1 | grep -qw nextprotoneg
# if [ $? -eq 0 ]; then
# $OPENSSL s_client -host $NODE -port $PORT -nextprotoneg $NPN_PROTOs $SNI </dev/null 2>/dev/null >$TMPFILE
# if [ $? -eq 0 ]; then
# echo
2015-01-29 09:33:35 +01:00
# pr_bold "CRIME Vulnerability, SPDY \c" ; outln "(CVE-2012-4929): \c"
2014-07-01 16:28:16 +02:00
# STR=`grep Compression $TMPFILE `
# if echo $STR | grep -q NONE >/dev/null; then
2015-01-29 09:33:35 +01:00
# pr_green "not vulnerable (OK)"
2014-07-01 16:28:16 +02:00
# ret=`expr $ret + 0`
# else
2015-02-21 11:47:12 +01:00
# pr_red "VULNERABLE (NOT ok)"
2014-07-01 16:28:16 +02:00
# ret=`expr $ret + 1`
# fi
# fi
# fi
2014-07-16 19:04:15 +02:00
[ $VERBERR -eq 0 ] && outln " $STR "
2014-07-01 16:28:16 +02:00
#echo
2015-02-11 09:43:04 +01:00
tmpfile_handle $FUNCNAME .txt
2014-07-01 16:28:16 +02:00
return $ret
}
2015-01-20 21:59:21 +01:00
2015-01-20 21:51:49 +01:00
# Browser Exploit Against SSL/TLS
2014-07-01 16:28:16 +02:00
beast( ) {
2015-01-20 21:59:21 +01:00
shopt -s lastpipe # otherwise it's more tricky to access variables in a while loop
local hexcode dash cbc_cipher sslvers kx auth enc mac export
2015-01-20 21:51:49 +01:00
local detected_proto
2015-01-21 12:53:00 +01:00
local detected_cbc_cipher = ""
2015-01-20 21:51:49 +01:00
local higher_proto_supported = ""
2015-01-20 21:59:21 +01:00
local -i ret = 0
local spaces = " "
2015-01-20 21:51:49 +01:00
#in a nutshell: don't use CBC Ciphers in SSLv3 TLSv1.0
2015-01-29 10:46:16 +01:00
2015-01-29 09:33:35 +01:00
pr_bold " BEAST" ; out " (CVE-2011-3389) "
2015-01-20 21:51:49 +01:00
2015-01-20 21:59:21 +01:00
# 2) test handfull of common CBC ciphers
for proto in ssl3 tls1; do
$OPENSSL s_client -" $proto " $STARTTLS -connect $NODEIP :$PORT $SNI >$TMPFILE 2>/dev/null </dev/null
if [ $? -ne 0 ] ; then
continue # protocol no supported, so we do not need to check each cipher with that protocol
fi
$OPENSSL ciphers -V 'ALL:eNULL' | grep CBC | while read hexcode dash cbc_cipher sslvers kx auth enc mac export ; do
$OPENSSL s_client -cipher " $cbc_cipher " -" $proto " $STARTTLS -connect $NODEIP :$PORT $SNI >$TMPFILE 2>/dev/null </dev/null
#normalize_ciphercode $hexcode
#neat_list $HEXC $ciph $kx $enc | strings | grep -wai "$arg"
if [ $? -eq 0 ] ; then
detected_cbc_cipher = " $detected_cbc_cipher " " $( grep -w "Cipher" $TMPFILE | egrep -vw "New|is" | sed -e 's/^.*Cipher.*://' -e 's/ //g' ) "
fi
done
#detected_cbc_cipher=`echo $detected_cbc_cipher | sed 's/ //g'`
if [ -z " $detected_cbc_cipher " ] ; then
2015-02-03 23:20:59 +01:00
pr_litegreenln " no CBC ciphers for $( echo $proto | tr '[a-z]' '[A-Z]' ) (OK) "
2015-01-20 21:59:21 +01:00
else
detected_cbc_cipher = $( echo " $detected_cbc_cipher " | sed -e 's/ /\n ' " ${ spaces } " '/9' -e 's/ /\n ' " ${ spaces } " '/6' -e 's/ /\n ' " ${ spaces } " '/3' )
[ $ret -eq 1 ] && out " $spaces "
2015-01-29 09:33:35 +01:00
out " $( echo $proto | tr '[a-z]' '[A-Z]' ) : " ; pr_brownln " $detected_cbc_cipher "
2015-01-20 21:59:21 +01:00
ret = 1
detected_cbc_cipher = ""
fi
done
# 2) support for TLS 1.1+1.2?
2015-01-20 21:51:49 +01:00
for proto in tls1_1 tls1_2; do
$OPENSSL s_client -state -" $proto " $STARTTLS -connect $NODEIP :$PORT $SNI 2>/dev/null >$TMPFILE </dev/null
if [ $? -eq 0 ] ; then
higher_proto_supported = " $higher_proto_supported " " $( grep -w "Protocol" $TMPFILE | sed -e 's/^.*Protocol .*://' -e 's/ //g' ) "
fi
done
2015-01-29 23:20:58 +01:00
if [ $ret -eq 1 ] ; then
[ ! -z " $higher_proto_supported " ] && outln " $spaces but also supports higher protocols (possible mitigation): $higher_proto_supported "
fi
2015-01-20 21:51:49 +01:00
2015-01-20 21:59:21 +01:00
# printf "For a full individual test of each CBC cipher suites support by your $OPENSSL run \"$0 -x CBC $NODE\"\n"
2015-01-20 21:51:49 +01:00
2015-01-20 21:59:21 +01:00
shopt -u lastpipe # othwise for some reason it segfaults
2015-02-11 09:43:04 +01:00
tmpfile_handle $FUNCNAME .txt
2015-01-20 21:59:21 +01:00
return $ret
2014-07-01 16:28:16 +02:00
}
youknowwho( ) {
# CVE-2013-2566,
# NOT FIXME as there's no code: http://www.isg.rhul.ac.uk/tls/
# http://blog.cryptographyengineering.com/2013/03/attack-of-week-rc4-is-kind-of-broken-in.html
return 0
# in a nutshell: don't use RC4, really not!
}
old_fart( ) {
2015-01-29 09:33:35 +01:00
pr_magentaln " Your $OPENSSL $OSSL_VER version is an old fart... "
pr_magentaln "Get the precompiled bins, it doesn\'t make much sense to proceed"
2014-07-01 16:28:16 +02:00
exit 3
}
find_openssl_binary( ) {
# 0. check environment variable whether it's executable
if [ ! -z " $OPENSSL " ] && [ ! -x " $OPENSSL " ] ; then
2015-01-29 09:33:35 +01:00
pr_redln " \ncannot execute specified ( $OPENSSL ) openssl binary. "
2014-07-16 19:04:15 +02:00
outln "continuing ..."
2014-07-01 16:28:16 +02:00
fi
if [ -x " $OPENSSL " ] ; then
# 1. check environment variable
:
else
# 2. otherwise try openssl in path of testssl.sh
OPENSSL = $RUN_DIR /openssl
if [ ! -x $OPENSSL ] ; then
# 3. with arch suffix
OPENSSL = $RUN_DIR /openssl.` uname -m`
if [ ! -x $OPENSSL ] ; then
#4. finally: didn't fiond anything, so we take the one propably from system:
OPENSSL = ` which openssl`
fi
fi
fi
# http://www.openssl.org/news/openssl-notes.html
OSSL_VER = ` $OPENSSL version | awk -F' ' '{ print $2 }' `
OSSL_VER_MAJOR = ` echo " $OSSL_VER " | sed 's/\..*$//' `
OSSL_VER_MINOR = ` echo " $OSSL_VER " | sed -e 's/^.\.//' | sed 's/\..*.//' `
OSSL_VER_APPENDIX = ` echo " $OSSL_VER " | tr -d '[0-9.]' `
2014-11-19 13:22:22 +01:00
OSSL_VER_PLATFORM = ` $OPENSSL version -p | sed 's/^platform: //' `
2014-07-16 19:04:15 +02:00
OSSL_BUILD_DATE = ` $OPENSSL version -a | grep '^built' | sed -e 's/built on//' -e 's/: ... //' -e 's/: //' -e 's/ UTC//' -e 's/ +0000//' -e 's/.000000000//' `
2014-11-19 13:22:22 +01:00
echo $OSSL_BUILD_DATE | grep -q "not available" && OSSL_BUILD_DATE = ""
export OPENSSL OSSL_VER OSSL_BUILD_DATE OSSL_VER_PLATFORM
2014-07-01 16:28:16 +02:00
case " $OSSL_VER " in
0.9.7*| 0.9.6*| 0.9.5*)
# 0.9.5a was latest in 0.9.5 an released 2000/4/1, that'll NOT suffice for this test
old_fart ; ;
0.9.8)
case $OSSL_VER_APPENDIX in
a| b| c| d| e) old_fart; ; # no SNI!
2014-11-19 13:22:22 +01:00
# other than that we leave this for MacOSX but it's a pain and no guarantees!
2014-07-01 16:28:16 +02:00
esac
; ;
esac
2014-10-14 16:28:18 +02:00
if [ $OSSL_VER_MAJOR -lt 1 ] ; then ## mm: Patch for libressl
2014-11-19 13:22:22 +01:00
outln
2015-01-29 09:33:35 +01:00
pr_magentaln " ¡¡¡ <Enter> at your own risk !!! $OPENSSL is way too old (< version 1.0) "
2014-11-19 17:08:59 +01:00
outln " Proceeding may likely result in false negatives or positives\n"
2014-07-01 16:28:16 +02:00
read a
fi
return 0
}
starttls( ) {
2015-02-09 14:02:02 +01:00
protocol = ` echo " $1 " | sed 's/s$//' ` # strip trailing s in ftp(s), smtp(s), pop3(s), imap(s), ldap(s), telnet(s)
2014-07-01 16:28:16 +02:00
case " $1 " in
2015-02-09 14:02:02 +01:00
ftp| smtp| pop3| imap| xmpp| telnet| ldap)
2015-01-23 12:01:32 +01:00
outln " Trying STARTTLS via $( echo $protocol | tr '[a-z]' '[A-Z]' ) \n "
2014-07-01 16:28:16 +02:00
$OPENSSL s_client -connect $NODEIP :$PORT $SNI -starttls $protocol </dev/null >$TMPFILE 2>& 1
ret = $?
if [ $ret -ne 0 ] ; then
2015-01-29 09:33:35 +01:00
pr_bold " Problem: $OPENSSL couldn't estabilish STARTTLS via $protocol " ; outln
2014-07-01 16:28:16 +02:00
cat $TMPFILE
return 3
else
# now, this is lame: normally this should be handled by top level. Then I need to do proper parsing
# of the cmdline e.g. with getopts.
STARTTLS = " -starttls $protocol "
export STARTTLS
runprotocols ; ret = ` expr $? + $ret `
run_std_cipherlists ; ret = ` expr $? + $ret `
2014-12-21 00:47:23 +01:00
server_preference ; ret = ` expr $? + $ret `
2014-12-18 09:33:24 +01:00
server_defaults ; ret = ` expr $? + $ret `
2014-07-01 16:28:16 +02:00
2015-01-29 09:33:35 +01:00
outln; pr_blue "--> Testing specific vulnerabilities" ; outln "\n"
2014-07-01 16:28:16 +02:00
#FIXME: heartbleed + CCS won't work this way yet
# heartbleed ; ret=`expr $? + $ret`
# ccs_injection ; ret=`expr $? + $ret`
renego ; ret = ` expr $? + $ret `
crime ; ret = ` expr $? + $ret `
2015-01-20 21:59:21 +01:00
poodle ; ret = ` expr $? + $ret `
2014-07-01 16:28:16 +02:00
beast ; ret = ` expr $? + $ret `
2014-07-16 19:04:15 +02:00
2015-01-23 12:01:32 +01:00
rc4 ; ret = ` expr $? + $ret `
pfs ; ret = ` expr $? + $ret `
2014-07-16 19:04:15 +02:00
outln
#cipher_per_proto ; ret=`expr $? + $ret`
allciphers ; ret = ` expr $? + $ret `
2014-07-01 16:28:16 +02:00
fi
; ;
2015-02-09 14:02:02 +01:00
*) pr_litemagentaln "momentarily only ftp, smtp, pop3, imap, xmpp and telnet, ldap allowed" >& 2
2014-07-01 16:28:16 +02:00
ret = 2
; ;
esac
2015-02-11 09:43:04 +01:00
tmpfile_handle $FUNCNAME .txt
2014-07-01 16:28:16 +02:00
return $ret
}
help( ) {
PRG = ` basename $0 `
cat << EOF
2014-11-18 10:29:11 +01:00
$PRG <options>
<-h| --help> what you' re looking at
<-b| --banner> displays banner + version
<-v| --version> same as above
<-V| --local> pretty print all local ciphers
2014-12-08 10:32:51 +01:00
<-V| --local> pattern what local cipher with <pattern> is a/v?
2014-07-01 16:28:16 +02:00
2014-11-18 10:29:11 +01:00
$PRG <options> URI
2014-07-01 16:28:16 +02:00
2014-11-18 10:29:11 +01:00
<-e| --each-cipher> check each local ciphers remotely
<-E| -ee| --cipher-per-proto> check those per protocol
<-f| --ciphers> check cipher suites
<-p| --protocols> check TLS/SSL protocols only
2015-01-30 16:26:55 +01:00
<-S| --server_defaults> displays the servers default picks and certificate info
2014-11-18 10:29:11 +01:00
<-P| --preference> displays the servers picks: protocol+cipher
<-y| --spdy> checks for SPDY/NPN
<-x| --single-ciphers-test> <pattern> tests matched <pattern> of cipher
<-B| --heartbleed> tests only for heartbleed vulnerability
<-I| --ccs| --ccs_injection> tests only for CCS injection vulnerability
<-R| --renegotiation> tests only for renegotiation vulnerability
<-C| --compression| --crime> tests only for CRIME vulnerability
<-T| --breach> tests only for BREACH vulnerability
<-0| --poodle> tests only for POODLE vulnerability
2015-01-20 21:59:21 +01:00
<-A| --beast> tests only for BEAST vulnerability
2014-11-18 10:29:11 +01:00
<-s| --pfs| --fs| --nsa> checks ( perfect) forward secrecy settings
<-4| --rc4| --appelbaum> which RC4 ciphers are being offered?
<-H| --header| --headers> check for HSTS, HPKP and server/application banner string
2014-07-01 16:28:16 +02:00
2014-12-08 10:32:51 +01:00
<-t| --starttls> protocol does a default run against a STARTTLS enabled service
2014-07-01 16:28:16 +02:00
2014-12-08 10:32:51 +01:00
partly mandatory parameters:
2014-07-01 16:28:16 +02:00
2014-12-08 10:32:51 +01:00
URI host| host:port| URL| URL:port ( port 443 is assumed unless otherwise specified)
pattern an ignore case word pattern of cipher hexcode or any other string in the name, kx or bits
2015-02-09 14:02:02 +01:00
protocol is one of ftp,smtp,pop3,imap,xmpp,telnet,ldap ( for the latter two you need e.g. the supplied openssl)
2014-07-01 16:28:16 +02:00
EOF
return $?
}
mybanner( ) {
me = ` basename $0 `
osslver = ` $OPENSSL version`
osslpath = ` which $OPENSSL `
2014-12-21 23:22:50 +01:00
nr_ciphers = ` $OPENSSL ciphers 'ALL:COMPLEMENTOFALL:@STRENGTH' | sed 's/:/ /g' | wc -w`
2014-07-01 16:28:16 +02:00
hn = ` hostname`
2014-11-18 10:29:11 +01:00
#poor man's ident (nowadays ident not neccessarily installed)
2014-07-16 19:04:15 +02:00
idtag = ` grep '\$Id' $0 | grep -w Exp | grep -v grep | sed -e 's/^# //' -e 's/\$ $/\$/' `
2015-01-29 09:33:35 +01:00
[ " $COLOR " -ne 0 ] && idtag = " \033[1;30m $idtag \033[m\033[1m "
2014-07-01 16:28:16 +02:00
bb = ` cat <<EOF
2014-07-16 19:04:15 +02:00
#########################################################
2014-07-01 16:28:16 +02:00
$me v$VERSION ( $SWURL )
2014-11-17 18:49:56 +01:00
( $idtag )
2014-07-01 16:28:16 +02:00
This program is free software. Redistribution +
modification under GPLv2 is permitted.
USAGE w/o ANY WARRANTY. USE IT AT YOUR OWN RISK!
2014-11-18 10:29:11 +01:00
Note: you can only check the server with what is
available ( ciphers/protocols) locally on your machine!
2014-07-16 19:04:15 +02:00
#########################################################
2014-07-01 16:28:16 +02:00
EOF
`
2015-01-29 09:33:35 +01:00
pr_bold " $bb "
2014-07-16 19:04:15 +02:00
outln "\n"
2015-01-23 12:17:27 +01:00
outln " Using \" $osslver \" [~ $nr_ciphers ciphers] on
2014-11-19 13:22:22 +01:00
$hn :$osslpath
( built: \" $OSSL_BUILD_DATE \" , platform: \" $OSSL_VER_PLATFORM \" ) \n "
2014-07-01 16:28:16 +02:00
}
maketempf ( ) {
2014-12-18 09:33:24 +01:00
TEMPDIR = ` mktemp -d /tmp/ssltester.XXXXXX` || exit 6
TMPFILE = $TEMPDIR /tempfile.txt || exit 6
HOSTCERT = $TEMPDIR /host_cerificate.txt
HEADERFILE = $TEMPDIR /http_header.txt
HEADERFILE_BREACH = $TEMPDIR /http_header_breach.txt
LOGFILE = $TEMPDIR /logfile.txt
2015-01-21 12:53:00 +01:00
if [ $DEBUG -ne 0 ] ; then
cat >$TEMPDIR /environment.txt << EOF
PID: $$
bash version: ${ BASH_VERSINFO [0] } .${ BASH_VERSINFO [1] } .${ BASH_VERSINFO [2] }
status: ${ BASH_VERSINFO [4] }
machine: ${ BASH_VERSINFO [5] }
shellopts: $SHELLOPTS
" $osslver " [ $nr_ciphers ciphers] on $hn :$osslpath
built: " $OSSL_BUILD_DATE " , platform: " $OSSL_VER_PLATFORM "
$idtag
PATH: $PATH
RUN_DIR: $RUN_DIR
CAPATH: $CAPATH
ECHO: $ECHO
COLOR: $COLOR
SHOW_LOC_CIPH: $SHOW_LOC_CIPH
VERBERR: $VERBERR
LOCERR: $LOCERR
SHOW_EACH_C: $SHOW_EACH_C
SNEAKY: $SNEAKY
DEBUG: $DEBUG
HSTS_MIN: $HSTS_MIN
HPKP_MIN: $HPKP_MIN
MAX_WAITSOCK: $MAX_WAITSOCK
HEADER_MAXSLEEP: $HEADER_MAXSLEEP
CLIENT_MIN_PFS: $CLIENT_MIN_PFS
DAYS2WARN1: $DAYS2WARN1
DAYS2WARN2: $DAYS2WARN2
EOF
$OPENSSL ciphers -V $1 & >$TEMPDIR /all_local_ciphers.txt
fi
2014-07-01 16:28:16 +02:00
}
cleanup ( ) {
2015-01-21 12:53:00 +01:00
if [ [ " $DEBUG " -ge 1 ] ] ; then
2015-02-13 16:01:46 +01:00
outln "\n"
2015-01-29 09:33:35 +01:00
pr_underline " DEBUG (level $DEBUG ): see files in $TEMPDIR "
2014-07-01 16:28:16 +02:00
else
2014-12-18 09:33:24 +01:00
[ -d " $TEMPDIR " ] && rm -rf ${ TEMPDIR } ;
2014-07-01 16:28:16 +02:00
fi
2014-07-16 19:04:15 +02:00
outln
2014-11-18 23:14:17 +01:00
[ -n " $NODE " ] && datebanner "Done" # only if running against server
2014-07-16 19:04:15 +02:00
outln
2014-07-01 16:28:16 +02:00
}
2015-01-23 12:17:27 +01:00
# for now only GOST engine
2014-07-16 19:04:15 +02:00
initialize_engine( ) {
2015-01-28 06:17:27 +01:00
if uname -s | grep -q BSD || ! $OPENSSL engine gost -vvvv -t -c >/dev/null 2>& 1; then
2015-01-29 09:33:35 +01:00
pr_litemagenta " No engine or GOST support via engine with your $OPENSSL " ; outln "\n"
2014-07-16 19:04:15 +02:00
return 1
2015-01-28 06:17:27 +01:00
elif echo $osslver | grep -q LibreSSL; then
return 1
else
2014-12-19 17:02:26 +01:00
if [ ! -z " $OPENSSL_CONF " ] ; then
2015-01-29 09:33:35 +01:00
pr_litemagenta "For now I am providing the config file in to have GOST support" ; outln
2014-12-19 17:02:26 +01:00
else
2015-01-20 21:51:49 +01:00
[ -z " $TEMPDIR " ] && maketempf
2015-01-08 14:16:22 +01:00
OPENSSL_CONF = $TEMPDIR /gost.conf || exit 6
2014-07-16 19:04:15 +02:00
# see https://www.mail-archive.com/openssl-users@openssl.org/msg65395.html
2014-12-19 17:02:26 +01:00
cat >$OPENSSL_CONF << EOF
2014-07-16 19:04:15 +02:00
openssl_conf = openssl_def
[ openssl_def ]
engines = engine_section
[ engine_section ]
gost = gost_section
[ gost_section ]
engine_id = gost
default_algorithms = ALL
CRYPT_PARAMS = id-Gost28147-89-CryptoPro-A-ParamSet
EOF
2014-12-19 17:02:26 +01:00
export OPENSSL_CONF
2014-07-16 19:04:15 +02:00
fi
fi
return 0
}
ignore_no_or_lame( ) {
2015-01-06 16:25:19 +01:00
[ " $WARNINGS " = "off" -o " $WARNINGS " = "false" ] && return 0
[ " $WARNINGS " = "batch" ] && return 1
2015-01-29 09:33:35 +01:00
pr_magenta " $1 "
2014-07-01 16:28:16 +02:00
read a
case $a in
2014-07-16 19:04:15 +02:00
Y| y| Yes| YES| yes)
return 0; ;
default)
; ;
2014-07-01 16:28:16 +02:00
esac
return 1
}
2014-07-16 19:04:15 +02:00
2014-07-01 16:28:16 +02:00
parse_hn_port( ) {
PORT = 443 # unless otherwise auto-determined, see below
NODE = " $1 "
# strip "https" and trailing urlpath supposed it was supplied additionally
echo $NODE | grep -q 'https://' && NODE = ` echo $NODE | sed -e 's/https\:\/\///' `
# strip trailing urlpath
NODE = ` echo $NODE | sed -e 's/\/.*$//' `
2014-07-16 19:04:15 +02:00
# was the address supplied like [AA:BB:CC::]:port ?
if echo $NODE | grep -q ']' ; then
tmp_port = ` printf $NODE | sed 's/\[.*\]//' | sed 's/://' `
# determine v6 port, supposed it was supplied additionally
if [ ! -z " $tmp_port " ] ; then
PORT = $tmp_port
NODE = ` printf $NODE | sed " s/: $PORT // " `
fi
NODE = ` printf $NODE | sed -e 's/\[//' -e 's/\]//' `
else
# determine v4 port, supposed it was supplied additionally
echo $NODE | grep -q ':' && PORT = ` echo $NODE | sed 's/^.*\://' ` && NODE = ` echo $NODE | sed 's/\:.*$//' `
fi
SNI = " -servername $NODE "
2014-07-01 16:28:16 +02:00
2015-02-12 13:40:53 +01:00
URL_PATH = ` echo $1 | sed 's/.*' " ${ NODE } " '//' | sed 's/.*' " ${ PORT } " '//' ` # remove protocol and node part and port
URL_PATH = ` echo $URL_PATH | sed 's/\/\//\//g' ` # we rather want // -> /
2014-07-01 16:28:16 +02:00
2014-07-16 19:04:15 +02:00
# now get NODEIP
get_dns_entries
2014-10-07 12:04:21 +02:00
# check if we can connect to port
if ! fd_socket; then
ignore_no_or_lame "Ignore? "
[ $? -ne 0 ] && exit 3
2014-07-01 16:28:16 +02:00
fi
2014-10-07 12:04:21 +02:00
close_socket
2014-07-01 16:28:16 +02:00
2014-11-30 01:30:20 +01:00
if [ [ -z " $2 " ] ] ; then # for starttls we don't want this check
2014-07-01 16:28:16 +02:00
# is ssl service listening on port? FIXME: better with bash on IP!
2014-07-16 19:04:15 +02:00
$OPENSSL s_client -connect " $NODE : $PORT " $SNI </dev/null >/dev/null 2>& 1
2014-07-01 16:28:16 +02:00
if [ $? -ne 0 ] ; then
2015-01-29 09:33:35 +01:00
pr_boldln " $NODE : $PORT doesn't seem a TLS/SSL enabled server or it requires a certificate " ;
2015-01-06 16:25:19 +01:00
ignore_no_or_lame "Proceed (note that the results might look ok but they are nonsense) ? "
[ $? -ne 0 ] && exit 3
2014-07-01 16:28:16 +02:00
fi
fi
datebanner "Testing"
2015-02-04 09:48:34 +01:00
[ [ -z " $2 " ] ] && runs_HTTP # for starttls we don't check the protocol as it is supplied on the cmd line
2014-07-16 19:04:15 +02:00
initialize_engine
2014-07-01 16:28:16 +02:00
}
2014-07-16 19:04:15 +02:00
get_dns_entries( ) {
2014-10-07 11:14:39 +02:00
test4iponly = ` printf $NODE | sed -e 's/[0-9]//g' -e 's/\.//g' `
if [ " x $test4iponly " = = "x" ] ; then # only an IPv4 address was supplied
IP4 = $NODE
SNI = "" # override this as we test the IP only
else
# for security testing sometimes we have local host entries, so getent is preferred
2014-11-22 03:57:36 +01:00
if which getent & >/dev/null; then
2014-10-07 11:14:39 +02:00
getent ahostsv4 $NODE 2>/dev/null >/dev/null
if [ $? -eq 0 ] ; then
2014-11-18 23:14:17 +01:00
# Linux:
IP4 = ` getent ahostsv4 $NODE 2>/dev/null | grep -v ':' | grep STREAM | awk '{ print $1}' | uniq`
#else
# IP4=`getent hosts $NODE 2>/dev/null | grep -v ':' | awk '{ print $1}' | uniq`
#FIXME: FreeBSD returns only one entry
2014-10-07 11:14:39 +02:00
fi
2014-07-16 19:04:15 +02:00
fi
2014-11-18 23:14:17 +01:00
if [ -z " $IP4 " ] ; then # getent returned nothing:
2015-02-03 23:20:59 +01:00
IP4 = ` host -t a $NODE 2>/dev/null | grep -v alias | sed 's/^.*address //' `
2014-10-09 11:22:23 +02:00
if echo " $IP4 " | grep -q NXDOMAIN || echo " $IP4 " | grep -q "no A record" ; then
2015-01-29 09:33:35 +01:00
pr_magenta " Can't proceed: No IP address for \" $NODE \" available " ; outln "\n"
2014-10-07 11:14:39 +02:00
exit 1
fi
2014-07-16 19:04:15 +02:00
fi
2015-02-03 23:20:59 +01:00
# MSYS2 has no host or getent, so we do this
if [ -z " $IP4 " ] ; then
IP4 = ` nslookup $NODE 2>/dev/null | grep -A10 Name | grep -v Name | sed 's/^Address.*: .//' `
fi
2014-07-01 16:28:16 +02:00
2014-10-07 11:14:39 +02:00
# for IPv6 we often get this :ffff:IPV4 address which isn't of any use
#which getent 2>&1 >/dev/null && IP6=`getent ahostsv6 $NODE | grep $NODE | awk '{ print $1}' | grep -v '::ffff' | uniq`
if [ -z " $IP6 " ] ; then
2015-01-21 12:53:00 +01:00
if host -t aaaa $NODE & >/dev/null ; then
2014-10-07 11:14:39 +02:00
IP6 = ` host -t aaaa $NODE | grep -v alias | grep -v "no AAAA record" | sed 's/^.*address //' `
else
IP6 = ""
fi
2014-07-16 19:04:15 +02:00
fi
2015-02-03 23:20:59 +01:00
# MSYS2 has no host or getent, so we do this
if [ -z " $IP6 " ] ; then
IP6 = ` nslookup -type= aaaa $NODE 2>/dev/null | grep -A10 Name | grep -v Name | sed 's/^Address.*: .//' `
fi
2014-10-09 11:22:23 +02:00
fi # test4iponly
2014-07-16 19:04:15 +02:00
2014-07-01 16:28:16 +02:00
IPADDRs = ` echo $IP4 `
[ ! -z " $IP6 " ] && IPADDRs = ` echo $IP4 ` " " ` echo $IP6 `
2015-02-03 23:20:59 +01:00
# FIXME: we could/should test more than one IPv4 addresses if available, same IPv6. For now we test the first IPv4:
2014-07-01 16:28:16 +02:00
NODEIP = ` echo " $IP4 " | head -1`
2014-07-16 19:04:15 +02:00
2015-02-03 23:20:59 +01:00
# we can't do this as some checks and even openssl are not yet IPv6 safe. BTW: bash sockets do IPv6 transparently!
2014-07-16 19:04:15 +02:00
#NODEIP=`echo "$IP6" | head -1`
2015-01-21 12:53:00 +01:00
rDNS = ` host -t PTR $NODEIP 2>/dev/null | grep -v "is an alias for" | sed -e 's/^.*pointer //' -e 's/\.$//' `
2014-07-01 16:28:16 +02:00
echo $rDNS | grep -q NXDOMAIN && rDNS = " - "
}
2014-11-30 01:30:20 +01:00
2014-07-16 19:04:15 +02:00
display_rdns_etc( ) {
2014-11-30 01:30:20 +01:00
if [ ` printf " $IPADDRs " | wc -w` -gt 1 ] ; then
2014-07-16 19:04:15 +02:00
out " further IP addresses: "
2014-07-01 16:28:16 +02:00
for i in $IPADDRs ; do
[ " $i " = = " $NODEIP " ] && continue
2014-07-16 19:04:15 +02:00
out " $i "
2014-07-01 16:28:16 +02:00
done
2014-07-16 19:04:15 +02:00
outln
fi
if [ -n " $rDNS " ] ; then
2015-02-13 16:01:46 +01:00
printf " %-23s %s" " rDNS ( $NODEIP ): " " $rDNS "
2014-07-01 16:28:16 +02:00
fi
}
datebanner( ) {
tojour = ` date +%F` " " ` date +%R`
2014-11-18 23:14:17 +01:00
outln
2015-01-29 09:33:35 +01:00
pr_reverse " $1 now ( $tojour ) ---> $NODEIP : $PORT ( $NODE ) <--- " ; outln "\n"
2014-11-18 23:14:17 +01:00
if [ " $1 " = "Testing" ] ; then
2014-07-16 19:04:15 +02:00
display_rdns_etc
fi
outln
2014-07-01 16:28:16 +02:00
}
################# main: #################
case " $1 " in
-h| --help| -help| "" )
help
exit $? ; ;
esac
# auto determine where bins are
find_openssl_binary
mybanner
#PATH_TO_TESTSSL="$(cd "${0%/*}" 2>/dev/null; echo "$PWD"/"${0##*/}")"
PATH_TO_TESTSSL = ` readlink " $BASH_SOURCE " ` 2>/dev/null
[ -z $PATH_TO_TESTSSL ] && PATH_TO_TESTSSL = "."
2014-11-17 18:49:56 +01:00
#
# next file provides a pair "keycode/ RFC style name", see the RFCs, cipher(1) and
# https://www.carbonwind.net/TLS_Cipher_Suites_Project/tls_ssl_cipher_suites_simple_table_all.htm
[ -r " $( dirname $PATH_TO_TESTSSL ) /mapping-rfc.txt " ] && MAP_RFC_FNAME = ` dirname $PATH_TO_TESTSSL ` "/mapping-rfc.txt"
2014-07-01 16:28:16 +02:00
#FIXME: I know this sucks and getoptS is better
case " $1 " in
-b| --banner| -banner| -v| --version| -version)
exit 0
; ;
-V| --local)
2014-07-16 19:04:15 +02:00
initialize_engine # GOST support
2014-07-01 16:28:16 +02:00
prettyprint_local " $2 "
exit $? ; ;
2014-11-18 10:29:11 +01:00
-x| --single-ciphers-test)
2014-08-29 14:57:20 +02:00
maketempf
2014-11-30 01:30:20 +01:00
parse_hn_port " $3 "
2014-08-29 14:57:20 +02:00
test_just_one $2
2015-01-20 21:51:49 +01:00
exit $? ; ;
2014-07-01 16:28:16 +02:00
-t| --starttls)
maketempf
2014-12-08 10:32:51 +01:00
parse_hn_port " $3 " " $2 " # here comes protocol to signal starttls and hostname:port
starttls " $2 " # protocol
2015-01-20 21:51:49 +01:00
exit $? ; ;
2014-07-01 16:28:16 +02:00
-e| --each-cipher)
maketempf
2014-11-30 01:30:20 +01:00
parse_hn_port " $2 "
2014-07-01 16:28:16 +02:00
allciphers
2015-01-20 21:51:49 +01:00
exit $? ; ;
2014-07-01 16:28:16 +02:00
-E| -ee| --cipher-per-proto)
maketempf
2014-11-30 01:30:20 +01:00
parse_hn_port " $2 "
2014-07-01 16:28:16 +02:00
cipher_per_proto
2015-01-20 21:51:49 +01:00
exit $? ; ;
2014-07-01 16:28:16 +02:00
-p| --protocols)
maketempf
2014-11-30 01:30:20 +01:00
parse_hn_port " $2 "
2014-07-01 16:28:16 +02:00
runprotocols ; ret = $?
spdy ; ret = ` expr $? + $ret `
exit $ret ; ;
-f| --ciphers)
maketempf
2014-11-30 01:30:20 +01:00
parse_hn_port " $2 "
2014-07-01 16:28:16 +02:00
run_std_cipherlists
2015-01-20 21:51:49 +01:00
exit $? ; ;
2014-12-18 09:33:24 +01:00
-S| --server_defaults)
2014-07-01 16:28:16 +02:00
maketempf
2014-11-30 01:30:20 +01:00
parse_hn_port " $2 "
2014-12-18 09:33:24 +01:00
server_defaults
2015-01-20 21:51:49 +01:00
exit $? ; ;
2014-12-21 00:47:23 +01:00
-P| --server_preference)
maketempf
parse_hn_port " $2 "
server_preference
2015-01-20 21:51:49 +01:00
exit $? ; ;
2014-07-01 16:28:16 +02:00
-y| --spdy| --google)
maketempf
2014-11-30 01:30:20 +01:00
parse_hn_port " $2 "
2014-07-01 16:28:16 +02:00
spdy
exit $? ; ;
-B| --heartbleet)
maketempf
2014-11-30 01:30:20 +01:00
parse_hn_port " $2 "
2015-01-29 09:33:35 +01:00
outln; pr_blue "--> Testing for heartbleed vulnerability" ; outln "\n"
2014-07-01 16:28:16 +02:00
heartbleed
exit $? ; ;
-I| --ccs| --ccs_injection)
maketempf
2014-11-30 01:30:20 +01:00
parse_hn_port " $2 "
2015-01-29 09:33:35 +01:00
outln; pr_blue "--> Testing for CCS injection vulnerability" ; outln "\n"
2014-07-01 16:28:16 +02:00
ccs_injection
exit $? ; ;
-R| --renegotiation)
maketempf
2014-11-30 01:30:20 +01:00
parse_hn_port " $2 "
2015-01-29 09:33:35 +01:00
outln; pr_blue "--> Testing for Renegotiation vulnerability" ; outln "\n"
2014-07-01 16:28:16 +02:00
renego
exit $? ; ;
-C| --compression| --crime)
maketempf
2014-11-30 01:30:20 +01:00
parse_hn_port " $2 "
2015-01-29 09:33:35 +01:00
outln; pr_blue "--> Testing for CRIME vulnerability" ; outln "\n"
2014-07-01 16:28:16 +02:00
crime
2015-01-20 21:51:49 +01:00
exit $? ; ;
2014-07-01 16:28:16 +02:00
-T| --breach)
maketempf
2014-11-30 01:30:20 +01:00
parse_hn_port " $2 "
2015-01-29 09:33:35 +01:00
outln; pr_blue "--> Testing for BREACH (HTTP compression) vulnerability" ; outln "\n"
2014-11-30 01:30:20 +01:00
if [ [ $SERVICE != "HTTP" ] ] ; then
2015-01-29 09:33:35 +01:00
pr_litemagentaln " Wrong usage: You're not targetting a HTTP service"
2014-11-30 01:30:20 +01:00
ret = 2
else
2015-01-14 12:23:53 +01:00
breach " $URL_PATH "
2014-11-30 01:30:20 +01:00
ret = $?
fi
2014-07-01 16:28:16 +02:00
ret = ` expr $? + $ret `
exit $ret ; ;
2014-10-15 13:10:06 +02:00
-0| --poodle)
maketempf
2014-11-30 01:30:20 +01:00
parse_hn_port " $2 "
2015-01-29 09:33:35 +01:00
outln; pr_blue "--> Testing for POODLE (Padding Oracle On Downgraded Legacy Encryption) vulnerability" ; outln "\n"
2014-10-15 13:10:06 +02:00
poodle
2015-01-20 21:51:49 +01:00
exit $? ; ;
2014-07-01 16:28:16 +02:00
-4| --rc4| --appelbaum)
maketempf
2014-11-30 01:30:20 +01:00
parse_hn_port " $2 "
2014-07-01 16:28:16 +02:00
rc4
2015-01-20 21:51:49 +01:00
exit $? ; ;
2014-07-01 16:28:16 +02:00
-s| --pfs| --fs| --nsa)
maketempf
2014-11-30 01:30:20 +01:00
parse_hn_port " $2 "
2014-07-01 16:28:16 +02:00
pfs
2015-01-20 21:51:49 +01:00
exit $? ; ;
2015-01-20 21:59:21 +01:00
-A| --beast)
2015-01-20 21:51:49 +01:00
maketempf
parse_hn_port " $2 "
beast
exit $? ; ;
2014-07-01 16:28:16 +02:00
-H| --header| --headers)
maketempf
2014-11-30 01:30:20 +01:00
parse_hn_port " $2 "
2015-01-29 09:33:35 +01:00
outln; pr_blue "--> Testing HTTP Header response" ; outln "\n"
2014-11-30 01:30:20 +01:00
if [ [ $SERVICE = = "HTTP" ] ] ; then
2015-01-14 12:23:53 +01:00
hsts " $URL_PATH "
hpkp " $URL_PATH "
2014-11-30 01:30:20 +01:00
ret = $?
2015-01-14 12:23:53 +01:00
serverbanner " $URL_PATH "
2014-11-30 01:30:20 +01:00
ret = ` expr $? + $ret `
2015-01-21 12:53:00 +01:00
applicationbanner " $URL_PATH "
ret = ` expr $? + $ret `
2015-01-14 12:23:53 +01:00
cookieflags " $URL_PATH "
2015-01-14 09:48:44 +01:00
ret = ` expr $? + $ret `
2014-11-30 01:30:20 +01:00
else
2015-01-29 09:33:35 +01:00
pr_litemagentaln " Wrong usage: You're not targetting a HTTP service"
2014-11-30 01:30:20 +01:00
ret = 2
fi
2014-07-01 16:28:16 +02:00
exit $ret ; ;
2014-11-19 22:23:13 +01:00
-*) help ; ; # wrong argument
2014-07-01 16:28:16 +02:00
*)
maketempf
2014-11-30 01:30:20 +01:00
parse_hn_port " $1 "
2014-07-01 16:28:16 +02:00
2014-11-30 01:30:20 +01:00
outln
2014-07-01 16:28:16 +02:00
runprotocols ; ret = $?
spdy ; ret = ` expr $? + $ret `
run_std_cipherlists ; ret = ` expr $? + $ret `
2014-12-21 00:47:23 +01:00
server_preference ; ret = ` expr $? + $ret `
2014-12-18 09:33:24 +01:00
server_defaults ; ret = ` expr $? + $ret `
2014-07-01 16:28:16 +02:00
2014-11-30 01:30:20 +01:00
if [ [ $SERVICE = = "HTTP" ] ] ; then
2015-01-29 09:33:35 +01:00
outln; pr_blue "--> Testing HTTP Header response"
2014-11-30 01:30:20 +01:00
outln "\n"
2015-01-15 20:29:46 +01:00
hsts " $URL_PATH " ; ret = ` expr $? + $ret `
hpkp " $URL_PATH " ; ret = ` expr $? + $ret `
serverbanner " $URL_PATH " ; ret = ` expr $? + $ret `
2015-01-21 12:53:00 +01:00
applicationbanner " $URL_PATH " ; ret = ` expr $? + $ret `
2015-01-15 20:29:46 +01:00
cookieflags " $URL_PATH " ; ret = ` expr $? + $ret `
2014-11-30 01:30:20 +01:00
fi
2014-07-01 16:28:16 +02:00
2015-01-29 09:33:35 +01:00
outln; pr_blue "--> Testing specific vulnerabilities"
2015-01-23 12:01:32 +01:00
outln "\n"
heartbleed ; ret = ` expr $? + $ret `
ccs_injection ; ret = ` expr $? + $ret `
renego ; ret = ` expr $? + $ret `
crime ; ret = ` expr $? + $ret `
[ [ $SERVICE = = "HTTP" ] ] && breach " $URL_PATH " ; ret = ` expr $? + $ret `
poodle ; ret = ` expr $? + $ret `
beast ; ret = ` expr $? + $ret `
2014-07-16 19:04:15 +02:00
rc4 ; ret = ` expr $? + $ret `
2014-07-01 16:28:16 +02:00
pfs ; ret = ` expr $? + $ret `
exit $ret ; ;
esac
2015-02-21 11:47:12 +01:00
# $Id: testssl.sh,v 1.193 2015/02/21 10:47:11 dirkw Exp $
2014-07-01 16:28:16 +02:00
# vim:ts=5:sw=5