1
0
mirror of https://github.com/drwetter/testssl.sh.git synced 2025-04-26 11:26:06 +02:00

jsonID, code housekeeping, some CWEs added, split time

As before (see ) and as indicated () some minor
changed to the jsonID have been taking place. Some
redundant verbosity has been eliminated, some IDs
changed the name.

For HTTP2 you should now ALPN_HTTP2.

Some obvious CWEs were added in the JSON section.
ke for null cipher list, information leakage in
the http headers. There's probably space for improvements.

A few early time marks were added to debug time spend.
This commit is contained in:
Dirk 2018-02-14 17:21:48 +01:00
parent 7b5a7579d7
commit 79427e3040

@ -1606,6 +1606,8 @@ match_ipv4_httpheader() {
local spaces=" " local spaces=" "
local count local count
local jsonID="ipv4_in_header" local jsonID="ipv4_in_header"
local cwe="CWE-212"
local cve=""
if [[ ! -s $HEADERFILE ]]; then if [[ ! -s $HEADERFILE ]]; then
run_http_header "$1" || return 1 run_http_header "$1" || return 1
@ -1627,7 +1629,7 @@ match_ipv4_httpheader() {
fi fi
pr_svrty_medium "$result" pr_svrty_medium "$result"
outln "\n$spaces$your_ip_msg" outln "\n$spaces$your_ip_msg"
fileout "$jsonID" "MEDIUM" "IPv4 address $result $your_ip_msg in header" fileout "$jsonID" "MEDIUM" "$result $your_ip_msg" "$cve" "$cwe"
fi fi
count=$count+1 count=$count+1
done < $HEADERFILE done < $HEADERFILE
@ -2125,7 +2127,7 @@ emphasize_stuff_in_headers(){
run_server_banner() { run_server_banner() {
local serverbanner local serverbanner
local jsonID="server_banner" local jsonID="banner_server"
if [[ ! -s $HEADERFILE ]]; then if [[ ! -s $HEADERFILE ]]; then
run_http_header "$1" || return 1 run_http_header "$1" || return 1
@ -2162,7 +2164,7 @@ run_appl_banner() {
local first=true local first=true
local spaces=" " local spaces=" "
local appl_banners="" local appl_banners=""
local jsonID="appl_banner" local jsonID="banner_application"
if [[ ! -s $HEADERFILE ]]; then if [[ ! -s $HEADERFILE ]]; then
run_http_header "$1" || return 1 run_http_header "$1" || return 1
@ -2195,6 +2197,9 @@ run_rp_banner() {
local first=true local first=true
local spaces=" " local spaces=" "
local rp_banners="" local rp_banners=""
local jsonID="banner_reverseproxy"
local cwe="CWE-200"
local cve=""
if [[ ! -s $HEADERFILE ]]; then if [[ ! -s $HEADERFILE ]]; then
run_http_header "$1" || return 1 run_http_header "$1" || return 1
@ -2203,7 +2208,7 @@ run_rp_banner() {
egrep -ai '^Via:|^X-Cache|^X-Squid|^X-Varnish:|^X-Server-Name:|^X-Server-Port:|^x-forwarded|^Forwarded' $HEADERFILE >$TMPFILE egrep -ai '^Via:|^X-Cache|^X-Squid|^X-Varnish:|^X-Server-Name:|^X-Server-Port:|^x-forwarded|^Forwarded' $HEADERFILE >$TMPFILE
if [[ $? -ne 0 ]]; then if [[ $? -ne 0 ]]; then
outln "--" outln "--"
fileout "rp_banner" "INFO" "No reverse proxy banner found" fileout "$jsonID" "INFO" "--" "$cve" "$cwe"
else else
while read line; do while read line; do
line=$(strip_lf "$line") line=$(strip_lf "$line")
@ -2215,7 +2220,7 @@ run_rp_banner() {
emphasize_stuff_in_headers "$line" emphasize_stuff_in_headers "$line"
rp_banners="${rp_banners}${line}" rp_banners="${rp_banners}${line}"
done < $TMPFILE done < $TMPFILE
fileout "rp_banner" "INFO" "Reverse proxy banner(s) found: $rp_banners" fileout "$jsonID" "INFO" "$rp_banners" "$cve" "$cwe"
fi fi
outln outln
@ -2232,6 +2237,8 @@ sub_f5_bigip_check() {
local routed_domain offset local routed_domain offset
local savedcookies="" local savedcookies=""
local spaces="$2" local spaces="$2"
local cwe="CWE-212"
local cve=""
# taken from https://github.com/drwetter/F5-BIGIP-Decoder, more details see there # taken from https://github.com/drwetter/F5-BIGIP-Decoder, more details see there
@ -2244,32 +2251,32 @@ sub_f5_bigip_check() {
ip="$(f5_ip_oldstyle "$cookievalue")" ip="$(f5_ip_oldstyle "$cookievalue")"
port="$(f5_port_decode $cookievalue)" port="$(f5_port_decode $cookievalue)"
out "${spaces}F5 cookie (default IPv4 pool member): "; pr_italic "$cookiename "; prln_svrty_medium "${ip}:${port}" out "${spaces}F5 cookie (default IPv4 pool member): "; pr_italic "$cookiename "; prln_svrty_medium "${ip}:${port}"
fileout "cookie_bigip_f5" "MEDIUM" "Information leakage: F5 cookie $cookiename $cookievalue is default IPv4 pool member ${ip}:${port}" fileout "cookie_bigip_f5" "MEDIUM" "Information leakage: F5 cookie $cookiename $cookievalue is default IPv4 pool member ${ip}:${port}" "$cve" "$cwe"
elif grep -q -E '^rd[0-9]{1,2}o0{20}f{4}[a-f0-9]{8}o[0-9]{1,5}' <<< "$cookievalue"; then elif grep -q -E '^rd[0-9]{1,2}o0{20}f{4}[a-f0-9]{8}o[0-9]{1,5}' <<< "$cookievalue"; then
routed_domain="$(f5_determine_routeddomain "$cookievalue")" routed_domain="$(f5_determine_routeddomain "$cookievalue")"
offset=$(( 2 + ${#routed_domain} + 1 + 24)) offset=$(( 2 + ${#routed_domain} + 1 + 24))
port="${cookievalue##*o}" port="${cookievalue##*o}"
ip="$(f5_hex2ip "${cookievalue:$offset:8}")" ip="$(f5_hex2ip "${cookievalue:$offset:8}")"
out "${spaces}F5 cookie (IPv4 pool in routed domain "; pr_svrty_medium "$routed_domain"; out "): "; pr_italic "$cookiename "; prln_svrty_medium "${ip}:${port}" out "${spaces}F5 cookie (IPv4 pool in routed domain "; pr_svrty_medium "$routed_domain"; out "): "; pr_italic "$cookiename "; prln_svrty_medium "${ip}:${port}"
fileout "cookie_bigip_f5" "MEDIUM" "Information leakage: F5 cookie $cookiename $cookievalue is IPv4 pool member in routed domain $routed_domain ${ip}:${port}" fileout "cookie_bigip_f5" "MEDIUM" "Information leakage: F5 cookie $cookiename $cookievalue is IPv4 pool member in routed domain $routed_domain ${ip}:${port}" "$cve" "$cwe"
elif grep -q -E '^vi[a-f0-9]{32}\.[0-9]{1,5}' <<< "$cookievalue"; then elif grep -q -E '^vi[a-f0-9]{32}\.[0-9]{1,5}' <<< "$cookievalue"; then
ip="$(f5_hex2ip6 ${cookievalue:2:32})" ip="$(f5_hex2ip6 ${cookievalue:2:32})"
port="${cookievalue##*.}" port="${cookievalue##*.}"
port=$(f5_port_decode "$port") port=$(f5_port_decode "$port")
out "${spaces}F5 cookie (default IPv6 pool member): "; pr_italic "$cookiename "; prln_svrty_medium "${ip}:${port}" out "${spaces}F5 cookie (default IPv6 pool member): "; pr_italic "$cookiename "; prln_svrty_medium "${ip}:${port}"
fileout "cookie_bigip_f5" "MEDIUM" "Information leakage: F5 cookie $cookiename $cookievalue is default IPv6 pool member ${ip}:${port}" fileout "cookie_bigip_f5" "MEDIUM" "Information leakage: F5 cookie $cookiename $cookievalue is default IPv6 pool member ${ip}:${port}" "$cve" "$cwe"
elif grep -q -E '^rd[0-9]{1,2}o[a-f0-9]{32}o[0-9]{1,5}' <<< "$cookievalue"; then elif grep -q -E '^rd[0-9]{1,2}o[a-f0-9]{32}o[0-9]{1,5}' <<< "$cookievalue"; then
routed_domain="$(f5_determine_routeddomain "$cookievalue")" routed_domain="$(f5_determine_routeddomain "$cookievalue")"
offset=$(( 2 + ${#routed_domain} + 1 )) offset=$(( 2 + ${#routed_domain} + 1 ))
port="${cookievalue##*o}" port="${cookievalue##*o}"
ip="$(f5_hex2ip6 ${cookievalue:$offset:32})" ip="$(f5_hex2ip6 ${cookievalue:$offset:32})"
out "${spaces}F5 cookie (IPv6 pool in routed domain "; pr_svrty_medium "$routed_domain"; out "): "; pr_italic "$cookiename "; prln_svrty_medium "${ip}:${port}" out "${spaces}F5 cookie (IPv6 pool in routed domain "; pr_svrty_medium "$routed_domain"; out "): "; pr_italic "$cookiename "; prln_svrty_medium "${ip}:${port}"
fileout "cookie_bigip_f5" "MEDIUM" "Information leakage: F5 cookie $cookiename $cookievalue is IPv6 pool member in routed domain $routed_domain ${ip}:${port}" fileout "cookie_bigip_f5" "MEDIUM" "Information leakage: F5 cookie $cookiename $cookievalue is IPv6 pool member in routed domain $routed_domain ${ip}:${port}" "$cve" "$cwe"
elif grep -q -E '^\!.*=$' <<< "$cookievalue"; then elif grep -q -E '^\!.*=$' <<< "$cookievalue"; then
if [[ "${#cookievalue}" -eq 81 ]] ; then if [[ "${#cookievalue}" -eq 81 ]] ; then
savedcookies="${savedcookies} ${cookiename}=${cookievalue:1:79}" savedcookies="${savedcookies} ${cookiename}=${cookievalue:1:79}"
out "${spaces}Encrypted F5 cookie named "; pr_italic "${cookiename}"; outln " detected" out "${spaces}Encrypted F5 cookie named "; pr_italic "${cookiename}"; outln " detected"
fileout "cookie_bigip_f5" "INFO" "encrypted F5 cookie named ${cookiename} detected" fileout "cookie_bigip_f5" "INFO" "encrypted F5 cookie named ${cookiename}"
fi fi
fi fi
done <<< "$allcookies" done <<< "$allcookies"
@ -2301,11 +2308,11 @@ run_cookie_flags() { # ARG1: Path
grep -ai '^Set-Cookie' $HEADERFILE >$TMPFILE grep -ai '^Set-Cookie' $HEADERFILE >$TMPFILE
if [[ $? -ne 0 ]]; then if [[ $? -ne 0 ]]; then
outln "(none issued at \"$1\")$msg302" outln "(none issued at \"$1\")$msg302"
fileout "cookie_count" "INFO" "No cookies issued at \"$1\"$msg302_" fileout "cookie_count" "INFO" "0 at \"$1\"$msg302_"
else else
nr_cookies=$(count_lines "$(cat $TMPFILE)") nr_cookies=$(count_lines "$(cat $TMPFILE)")
out "$nr_cookies issued: " out "$nr_cookies issued: "
fileout "cookie_count" "INFO" "$nr_cookies cookie(s) issued at \"$1\"$msg302_" fileout "cookie_count" "INFO" "$nr_cookies at \"$1\"$msg302_"
if [[ $nr_cookies -gt 1 ]]; then if [[ $nr_cookies -gt 1 ]]; then
negative_word="NONE" negative_word="NONE"
else else
@ -2318,9 +2325,9 @@ run_cookie_flags() { # ARG1: Path
esac esac
out " secure, " out " secure, "
if [[ $nr_cookies -eq $nr_secure ]]; then if [[ $nr_cookies -eq $nr_secure ]]; then
fileout "cookie_secure" "OK" "All $nr_cookies cookie(s) issued at \"$1\" marked as secure" fileout "cookie_secure" "OK" "All ($nr_cookies) at \"$1\" marked as secure"
else else
fileout "cookie_secure" "INFO" "$nr_secure/$nr_cookies cookie(s) issued at \"$1\" marked as secure" fileout "cookie_secure" "INFO" "$nr_secure/$nr_cookies at \"$1\" marked as secure"
fi fi
nr_httponly=$(grep -cai httponly $TMPFILE) nr_httponly=$(grep -cai httponly $TMPFILE)
case $nr_httponly in case $nr_httponly in
@ -2329,9 +2336,9 @@ run_cookie_flags() { # ARG1: Path
esac esac
out " HttpOnly" out " HttpOnly"
if [[ $nr_cookies -eq $nr_httponly ]]; then if [[ $nr_cookies -eq $nr_httponly ]]; then
fileout "cookie_httponly" "OK" "All $nr_cookies cookie(s) issued at \"$1\" marked as HttpOnly$msg302_" fileout "cookie_httponly" "OK" "All ($nr_cookies) at \"$1\" marked as HttpOnly$msg302_"
else else
fileout "cookie_httponly" "INFO" "$nr_secure/$nr_cookies cookie(s) issued at \"$1\" marked as HttpOnly$msg302_" fileout "cookie_httponly" "INFO" "$nr_secure/$nr_cookies at \"$1\" marked as HttpOnly$msg302_"
fi fi
outln "$msg302" outln "$msg302"
allcookies="$(awk '/[Ss][Ee][Tt]-[Cc][Oo][Oo][Kk][Ii][Ee]:/ { print $2 }' "$TMPFILE")" allcookies="$(awk '/[Ss][Ee][Tt]-[Cc][Oo][Oo][Kk][Ii][Ee]:/ { print $2 }' "$TMPFILE")"
@ -2388,7 +2395,7 @@ run_more_flags() {
if "$first"; then if "$first"; then
prln_svrty_medium "--" prln_svrty_medium "--"
fileout "sec_headers" "MEDIUM" "No security (or other interesting) headers detected" fileout "security_headers" "MEDIUM" "--"
fi fi
tmpfile_handle $FUNCNAME.txt tmpfile_handle $FUNCNAME.txt
@ -4286,6 +4293,7 @@ run_protocols() {
6) # couldn't open socket 6) # couldn't open socket
prln_fixme "couldn't open socket" prln_fixme "couldn't open socket"
fileout "$jsonID" "WARN" "couldn't be tested, socket problem" fileout "$jsonID" "WARN" "couldn't be tested, socket problem"
((ret++))
;; ;;
7) # strange reply, couldn't convert the cipher spec length to a hex number 7) # strange reply, couldn't convert the cipher spec length to a hex number
pr_cyan "strange v2 reply " pr_cyan "strange v2 reply "
@ -4314,11 +4322,11 @@ run_protocols() {
add_tls_offered ssl2 yes add_tls_offered ssl2 yes
if [[ 0 -eq "$nr_ciphers_detected" ]]; then if [[ 0 -eq "$nr_ciphers_detected" ]]; then
prln_svrty_high "supported but couldn't detect a cipher and vulnerable to CVE-2015-3197 "; prln_svrty_high "supported but couldn't detect a cipher and vulnerable to CVE-2015-3197 ";
fileout "$jsonID" "HIGH" "offered, vulnerable to CVE-2015-3197" fileout "$jsonID" "HIGH" "offered, no cipher" "CVE-2015-3197" "CWE-310"
else else
pr_svrty_critical "offered (NOT ok), also VULNERABLE to DROWN attack"; pr_svrty_critical "offered (NOT ok), also VULNERABLE to DROWN attack";
outln " -- $nr_ciphers_detected ciphers" outln " -- $nr_ciphers_detected ciphers"
fileout "$jsonID" "CRITICAL" "offered, vulnerable to DROWN attack. Detected ciphers: $nr_ciphers_detected" fileout "$jsonID" "CRITICAL" "vulnerable with $nr_ciphers_detected ciphers"
fi fi
fi fi
;; ;;
@ -4339,7 +4347,7 @@ run_protocols() {
add_tls_offered ssl2 no add_tls_offered ssl2 no
;; ;;
5) pr_svrty_high "CVE-2015-3197: $supported_no_ciph2"; 5) pr_svrty_high "CVE-2015-3197: $supported_no_ciph2";
fileout "$jsonID" "HIGH" "CVE-2015-3197: SSLv2 is $supported_no_ciph2" fileout "$jsonID" "HIGH" "offered, no cipher" "CVE-2015-3197" "CWE-310"
add_tls_offered ssl2 yes add_tls_offered ssl2 yes
;; ;;
7) fileout "$jsonID" "INFO" "not tested due to lack of local support" 7) fileout "$jsonID" "INFO" "not tested due to lack of local support"
@ -4384,10 +4392,8 @@ run_protocols() {
4) pr_fixme "signalled a 5xx after STARTTLS handshake"; outln "$debug_recomm" 4) pr_fixme "signalled a 5xx after STARTTLS handshake"; outln "$debug_recomm"
fileout "$jsonID" "WARN" "received 5xx after STARTTLS handshake reply (rerun with DEBUG>=2)" fileout "$jsonID" "WARN" "received 5xx after STARTTLS handshake reply (rerun with DEBUG>=2)"
;; ;;
5) pr_svrty_high "$supported_no_ciph2" 5) pr_svrty_high "$supported_no_ciph1" # protocol detected but no cipher --> comes from run_prototest_openssl
fileout "$jsonID" "HIGH" "$supported_no_ciph1" fileout "$jsonID" "HIGH" "$supported_no_ciph1"
outln "(may need debugging)"
((ret++))
add_tls_offered ssl3 yes add_tls_offered ssl3 yes
;; ;;
7) if "$using_sockets" ; then 7) if "$using_sockets" ; then
@ -4416,12 +4422,12 @@ run_protocols() {
latest_supported="0301" latest_supported="0301"
latest_supported_string="TLSv1.0" latest_supported_string="TLSv1.0"
add_tls_offered tls1 yes add_tls_offered tls1 yes
;; # nothing wrong with it -- per se ;; # nothing wrong with it -- per se
1) out "not offered" 1) out "not offered"
add_tls_offered tls1 no add_tls_offered tls1 no
if ! "$using_sockets" || [[ -z $latest_supported ]]; then if ! "$using_sockets" || [[ -z $latest_supported ]]; then
outln outln
fileout "$jsonID" "INFO" "not offered" # neither good or bad fileout "$jsonID" "INFO" "not offered" # neither good or bad
else else
prln_svrty_critical " -- connection failed rather than downgrading to $latest_supported_string (NOT ok)" prln_svrty_critical " -- connection failed rather than downgrading to $latest_supported_string (NOT ok)"
fileout "$jsonID" "CRITICAL" "connection failed rather than downgrading to $latest_supported_string" fileout "$jsonID" "CRITICAL" "connection failed rather than downgrading to $latest_supported_string"
@ -4450,7 +4456,7 @@ run_protocols() {
4) pr_fixme "signalled a 5xx after STARTTLS handshake"; outln "$debug_recomm" 4) pr_fixme "signalled a 5xx after STARTTLS handshake"; outln "$debug_recomm"
fileout "$jsonID" "WARN" "received 5xx after STARTTLS handshake reply (rerun with DEBUG>=2)" fileout "$jsonID" "WARN" "received 5xx after STARTTLS handshake reply (rerun with DEBUG>=2)"
;; ;;
5) outln "$supported_no_ciph1" # protocol ok, but no cipher 5) outln "$supported_no_ciph1" # protocol detected but no cipher --> comes from run_prototest_openssl
fileout "$jsonID" "INFO" "$supported_no_ciph1" fileout "$jsonID" "INFO" "$supported_no_ciph1"
add_tls_offered tls1 yes add_tls_offered tls1 yes
;; ;;
@ -4481,12 +4487,12 @@ run_protocols() {
latest_supported="0302" latest_supported="0302"
latest_supported_string="TLSv1.1" latest_supported_string="TLSv1.1"
add_tls_offered tls1_1 yes add_tls_offered tls1_1 yes
;; # nothing wrong with it ;; # nothing wrong with it
1) out "not offered" 1) out "not offered"
add_tls_offered tls1_1 no add_tls_offered tls1_1 no
if ! "$using_sockets" || [[ -z $latest_supported ]]; then if ! "$using_sockets" || [[ -z $latest_supported ]]; then
outln outln
fileout "$jsonID" "INFO" "is not offered" # neither good or bad fileout "$jsonID" "INFO" "is not offered" # neither good or bad
else else
prln_svrty_critical " -- connection failed rather than downgrading to $latest_supported_string" prln_svrty_critical " -- connection failed rather than downgrading to $latest_supported_string"
fileout "$jsonID" "CRITICAL" "connection failed rather than downgrading to $latest_supported_string" fileout "$jsonID" "CRITICAL" "connection failed rather than downgrading to $latest_supported_string"
@ -4518,10 +4524,10 @@ run_protocols() {
4) pr_fixme "signalled a 5xx after STARTTLS handshake"; outln "$debug_recomm" 4) pr_fixme "signalled a 5xx after STARTTLS handshake"; outln "$debug_recomm"
fileout "$jsonID" "WARN" "received 5xx after STARTTLS handshake reply (rerun with DEBUG>=2)" fileout "$jsonID" "WARN" "received 5xx after STARTTLS handshake reply (rerun with DEBUG>=2)"
;; ;;
5) outln "$supported_no_ciph1" 5) outln "$supported_no_ciph1" # protocol detected but no cipher --> comes from run_prototest_openssl
fileout "$jsonID" "INFO" "TLSv1.1 is $supported_no_ciph1" fileout "$jsonID" "INFO" "$supported_no_ciph1"
add_tls_offered tls1_1 yes add_tls_offered tls1_1 yes
;; # protocol ok, but no cipher ;;
7) if "$using_sockets" ; then 7) if "$using_sockets" ; then
# can only happen in debug mode # can only happen in debug mode
pr_warning "strange reply, maybe a client side problem with TLS 1.1"; outln "$debug_recomm" pr_warning "strange reply, maybe a client side problem with TLS 1.1"; outln "$debug_recomm"
@ -4597,10 +4603,10 @@ run_protocols() {
4) pr_fixme "signalled a 5xx after STARTTLS handshake"; outln "$debug_recomm" 4) pr_fixme "signalled a 5xx after STARTTLS handshake"; outln "$debug_recomm"
fileout "$jsonID" "WARN" "received 5xx after STARTTLS handshake reply (rerun with DEBUG>=2)" fileout "$jsonID" "WARN" "received 5xx after STARTTLS handshake reply (rerun with DEBUG>=2)"
;; ;;
5) outln "$supported_no_ciph1" 5) outln "$supported_no_ciph1" # protocol detected, but no cipher --> comes from run_prototest_openssl
fileout "$jsonID" "INFO" "is $supported_no_ciph1" fileout "$jsonID" "INFO" "$supported_no_ciph1"
add_tls_offered tls1_2 yes add_tls_offered tls1_2 yes
;; # protocol ok, but no cipher ;;
7) if "$using_sockets" ; then 7) if "$using_sockets" ; then
# can only happen in debug mode # can only happen in debug mode
pr_warning "strange reply, maybe a client side problem with TLS 1.2"; outln "$debug_recomm" pr_warning "strange reply, maybe a client side problem with TLS 1.2"; outln "$debug_recomm"
@ -4727,10 +4733,10 @@ run_protocols() {
4) pr_fixme "signalled a 5xx after STARTTLS handshake"; outln "$debug_recomm" 4) pr_fixme "signalled a 5xx after STARTTLS handshake"; outln "$debug_recomm"
fileout "$jsonID" "WARN" "received 5xx after STARTTLS handshake reply (rerun with DEBUG>=2)" fileout "$jsonID" "WARN" "received 5xx after STARTTLS handshake reply (rerun with DEBUG>=2)"
;; ;;
5) outln "$supported_no_ciph1" 5) outln "$supported_no_ciph1" # protocol detected but no cipher --> comes from run_prototest_openssl
fileout "$jsonID" "INFO" "is $supported_no_ciph1" fileout "$jsonID" "INFO" "$supported_no_ciph1"
add_tls_offered tls1_3 yes add_tls_offered tls1_3 yes
;; # protocol ok, but no cipher ;;
7) if "$using_sockets" ; then 7) if "$using_sockets" ; then
# can only happen in debug mode # can only happen in debug mode
prln_warning "strange reply, maybe a client side problem with TLS 1.3"; outln "$debug_recomm" prln_warning "strange reply, maybe a client side problem with TLS 1.3"; outln "$debug_recomm"
@ -4783,6 +4789,10 @@ run_cipherlists() {
# no SSLv2 here and in strong # no SSLv2 here and in strong
# ~ equivalent to 'grep AEAD etc/cipher-mapping.txt | grep -v Au=None' # ~ equivalent to 'grep AEAD etc/cipher-mapping.txt | grep -v Au=None'
local strong_ciphers="13,01, 13,02, 13,03, 13,04, 13,05, cc,14, cc,13, cc,15, c0,30, c0,2c, 00,a5, 00,a3, 00,a1, 00,9f, cc,a9, cc,a8, cc,aa, c0,af, c0,ad, c0,a3, c0,9f, 00,ad, 00,ab, cc,ae, cc,ad, cc,ac, c0,ab, c0,a7, c0,32, c0,2e, 00,9d, c0,a1, c0,9d, 00,a9, cc,ab, c0,a9, c0,a5, c0,51, c0,53, c0,55, c0,57, c0,59, c0,5d, c0,5f, c0,61, c0,63, c0,6b, c0,6d, c0,6f, c0,7b, c0,7d, c0,7f, c0,81, c0,83, c0,87, c0,89, c0,8b, c0,8d, c0,8f, c0,91, c0,93, 16,b7, 16,b8, 16,b9, 16,ba, c0,2f, c0,2b, 00,a4, 00,a2, 00,a0, 00,9e, c0,ae, c0,ac, c0,a2, c0,9e, 00,ac, 00,aa, c0,aa, c0,a6, c0,a0, c0,9c, 00,a8, c0,a8, c0,a4, c0,31, c0,2d, 00,9c, c0,50, c0,52, c0,54, c0,56, c0,58, c0,5c, c0,5e, c0,60, c0,62, c0,6a, c0,6c, c0,6e, c0,7a, c0,7c, c0,7e, c0,80, c0,82, c0,86, c0,88, c0,8a, c0,8c, c0,8e, c0,90, c0,92, 00,ff" local strong_ciphers="13,01, 13,02, 13,03, 13,04, 13,05, cc,14, cc,13, cc,15, c0,30, c0,2c, 00,a5, 00,a3, 00,a1, 00,9f, cc,a9, cc,a8, cc,aa, c0,af, c0,ad, c0,a3, c0,9f, 00,ad, 00,ab, cc,ae, cc,ad, cc,ac, c0,ab, c0,a7, c0,32, c0,2e, 00,9d, c0,a1, c0,9d, 00,a9, cc,ab, c0,a9, c0,a5, c0,51, c0,53, c0,55, c0,57, c0,59, c0,5d, c0,5f, c0,61, c0,63, c0,6b, c0,6d, c0,6f, c0,7b, c0,7d, c0,7f, c0,81, c0,83, c0,87, c0,89, c0,8b, c0,8d, c0,8f, c0,91, c0,93, 16,b7, 16,b8, 16,b9, 16,ba, c0,2f, c0,2b, 00,a4, 00,a2, 00,a0, 00,9e, c0,ae, c0,ac, c0,a2, c0,9e, 00,ac, 00,aa, c0,aa, c0,a6, c0,a0, c0,9c, 00,a8, c0,a8, c0,a4, c0,31, c0,2d, 00,9c, c0,50, c0,52, c0,54, c0,56, c0,58, c0,5c, c0,5e, c0,60, c0,62, c0,6a, c0,6c, c0,6e, c0,7a, c0,7c, c0,7e, c0,80, c0,82, c0,86, c0,88, c0,8a, c0,8c, c0,8e, c0,90, c0,92, 00,ff"
local cwe="CWE-327"
local cwe2="CWE-310"
local cve=""
"$SSL_NATIVE" && using_sockets=false "$SSL_NATIVE" && using_sockets=false
if ! "$using_sockets"; then if ! "$using_sockets"; then
@ -4803,18 +4813,18 @@ run_cipherlists() {
# argv[4]: string to be appended for fileout # argv[4]: string to be appended for fileout
# argv[5]: non-SSLv2 cipher list to test (hexcodes), if using sockets # argv[5]: non-SSLv2 cipher list to test (hexcodes), if using sockets
# argv[6]: SSLv2 cipher list to test (hexcodes), if using sockets # argv[6]: SSLv2 cipher list to test (hexcodes), if using sockets
sub_cipherlists 'NULL:eNULL' " NULL ciphers (no encryption) " -2 "NULL" "$null_ciphers" "$sslv2_null_ciphers" sub_cipherlists 'NULL:eNULL' " NULL ciphers (no encryption) " -2 "NULL" "$null_ciphers" "$sslv2_null_ciphers" "$cve" "$cwe"
ret=$? ret=$?
sub_cipherlists 'aNULL:ADH' " Anonymous NULL Ciphers (no authentication)" -2 "aNULL" "$anon_ciphers" "$sslv2_anon_ciphers" sub_cipherlists 'aNULL:ADH' " Anonymous NULL Ciphers (no authentication)" -2 "aNULL" "$anon_ciphers" "$sslv2_anon_ciphers" "$cve" "$cwe"
ret=$((ret + $?)) ret=$((ret + $?))
sub_cipherlists 'EXPORT:!ADH:!NULL' " Export ciphers (w/o ADH+NULL) " -2 "EXPORT" "$exp_ciphers" "$sslv2_exp_ciphers" sub_cipherlists 'EXPORT:!ADH:!NULL' " Export ciphers (w/o ADH+NULL) " -2 "EXPORT" "$exp_ciphers" "$sslv2_exp_ciphers" "$cve" "$cwe"
ret=$((ret + $?)) ret=$((ret + $?))
sub_cipherlists 'LOW:DES:!ADH:!EXP:!NULL' " LOW: 64 Bit + DES encryption (w/o export) " -2 "DES+64Bit" "$low_ciphers" "$sslv2_low_ciphers" sub_cipherlists 'LOW:DES:!ADH:!EXP:!NULL' " LOW: 64 Bit + DES encryption (w/o export) " -2 "DES+64Bit" "$low_ciphers" "$sslv2_low_ciphers" "$cve" "$cwe"
ret=$((ret + $?)) ret=$((ret + $?))
sub_cipherlists 'MEDIUM:!aNULL:!AES:!CAMELLIA:!ARIA:!CHACHA20:!3DES' \ sub_cipherlists 'MEDIUM:!aNULL:!AES:!CAMELLIA:!ARIA:!CHACHA20:!3DES' \
" Weak 128 Bit ciphers (SEED, IDEA, RC[2,4])" -1 "128Bit" "$medium_ciphers" "$sslv2_medium_ciphers" " Weak 128 Bit ciphers (SEED, IDEA, RC[2,4])" -1 "128Bit" "$medium_ciphers" "$sslv2_medium_ciphers" "$cve" "$cwe2"
ret=$((ret + $?)) ret=$((ret + $?))
sub_cipherlists '3DES:!aNULL:!ADH' " Triple DES Ciphers (Medium) " 0 "3DES" "$tdes_ciphers" "$sslv2_tdes_ciphers" sub_cipherlists '3DES:!aNULL:!ADH' " Triple DES Ciphers (Medium) " 0 "3DES" "$tdes_ciphers" "$sslv2_tdes_ciphers" "$cve" "$cwe2"
ret=$((ret + $?)) ret=$((ret + $?))
sub_cipherlists 'HIGH:!NULL:!aNULL:!DES:!3DES:!AESGCM:!CHACHA20:!AESGCM:!CamelliaGCM:!AESCCM8:!AESCCM'\ sub_cipherlists 'HIGH:!NULL:!aNULL:!DES:!3DES:!AESGCM:!CHACHA20:!AESGCM:!CamelliaGCM:!AESCCM8:!AESCCM'\
" High encryption (AES+Camellia, no AEAD) " 1 "HIGH" "$high_ciphers" "" " High encryption (AES+Camellia, no AEAD) " 1 "HIGH" "$high_ciphers" ""
@ -5154,6 +5164,8 @@ run_server_preference() {
local addcmd="" addcmd2="" local addcmd="" addcmd2=""
local using_sockets=true local using_sockets=true
local jsonID="cipher_order" local jsonID="cipher_order"
local cwe="CWE-310"
local cve=""
"$SSL_NATIVE" && using_sockets=false "$SSL_NATIVE" && using_sockets=false
@ -5217,7 +5229,7 @@ run_server_preference() {
pr_svrty_best "yes (OK)" pr_svrty_best "yes (OK)"
has_cipher_order=true has_cipher_order=true
limitedsense="" limitedsense=""
fileout "$jsonID" "OK" "sets cipher order" fileout "$jsonID" "OK" "server"
fi fi
debugme tm_out " $cipher1 | $cipher2" debugme tm_out " $cipher1 | $cipher2"
outln outln
@ -5891,7 +5903,7 @@ determine_trust() {
tls_time() { tls_time() {
local now difftime local now difftime
local spaces=" " local spaces=" "
local jsonID="TLS_time" local jsonID="TLS_timestamp"
pr_bold " TLS clock skew" ; out "$spaces" pr_bold " TLS clock skew" ; out "$spaces"
TLS_DIFFTIME_SET=true # this is a switch whether we want to measure the remote TLS_TIME TLS_DIFFTIME_SET=true # this is a switch whether we want to measure the remote TLS_TIME
@ -5905,17 +5917,17 @@ tls_time() {
if [[ "${#difftime}" -gt 5 ]]; then if [[ "${#difftime}" -gt 5 ]]; then
# openssl >= 1.0.1f fills this field with random values! --> good for possible fingerprint # openssl >= 1.0.1f fills this field with random values! --> good for possible fingerprint
out "Random values, no fingerprinting possible " out "Random values, no fingerprinting possible "
fileout "$jsonID" "INFO" "TLS timestamp is random" fileout "$jsonID" "INFO" "random"
else else
[[ $difftime != "-"* ]] && [[ $difftime != "0" ]] && difftime="+$difftime" [[ $difftime != "-"* ]] && [[ $difftime != "0" ]] && difftime="+$difftime"
out "$difftime"; out " sec from localtime"; out "$difftime"; out " sec from localtime";
fileout "$jsonID" "INFO" "TLS timestamp is off from your localtime by $difftime seconds" fileout "$jsonID" "INFO" "off by $difftime seconds from your localtime"
fi fi
debugme tm_out "$TLS_TIME" debugme tm_out "$TLS_TIME"
outln outln
else else
outln "SSLv3 through TLS 1.2 didn't return a timestamp" outln "SSLv3 through TLS 1.2 didn't return a timestamp"
fileout "$jsonID" "INFO" "No TLS timestamp returned by SSLv3 through TLSv1.2" fileout "$jsonID" "INFO" "None returned by SSLv3 through TLSv1.2"
fi fi
TLS_DIFFTIME_SET=false # reset the switch to save calls to date and friend in tls_sockets() TLS_DIFFTIME_SET=false # reset the switch to save calls to date and friend in tls_sockets()
return 0 return 0
@ -6855,7 +6867,7 @@ certificate_info() {
if [[ -n "$issuer_C" ]]; then if [[ -n "$issuer_C" ]]; then
issuerfinding+=" from " issuerfinding+=" from "
out " from " out " from "
# issuerfinding+="$issuer_C" issuerfinding+="$issuer_C"
pr_italic "$issuer_C" pr_italic "$issuer_C"
fi fi
issuerfinding+=")" issuerfinding+=")"
@ -7141,7 +7153,7 @@ certificate_info() {
must_staple "$json_postfix" "$provides_stapling" "$cert_txt" must_staple "$json_postfix" "$provides_stapling" "$cert_txt"
out "$indent"; pr_bold " DNS CAA RR"; out " (experimental) " out "$indent"; pr_bold " DNS CAA RR"; out " (experimental) "
jsonID="dns_CAArecord" jsonID="DNS_CAArecord"
caa_node="$NODE" caa_node="$NODE"
caa="" caa=""
while ( [[ -z "$caa" ]] && [[ ! -z "$caa_node" ]] ); do while ( [[ -z "$caa" ]] && [[ ! -z "$caa_node" ]] ); do
@ -7169,7 +7181,7 @@ certificate_info() {
fileout "${jsonID}${json_postfix}" "WARN" "check skipped as instructed" fileout "${jsonID}${json_postfix}" "WARN" "check skipped as instructed"
else else
pr_svrty_low "not offered" pr_svrty_low "not offered"
fileout "${jsonID}${json_postfix}" "LOW" "not offered" fileout "${jsonID}${json_postfix}" "LOW" "--"
fi fi
outln outln
@ -7924,7 +7936,7 @@ npn_pre(){
if [[ -n "$PROXY" ]]; then if [[ -n "$PROXY" ]]; then
[[ -n "$1" ]] && pr_warning "$1" [[ -n "$1" ]] && pr_warning "$1"
pr_warning "not tested as proxies do not support proxying it" pr_warning "not tested as proxies do not support proxying it"
fileout "SPDY-NPN" "WARN" "not tested as proxies do not support proxying it" fileout "NPN" "WARN" "not tested as proxies do not support proxying it"
return 1 return 1
fi fi
if ! "$HAS_SPDY"; then if ! "$HAS_SPDY"; then
@ -7939,12 +7951,12 @@ alpn_pre(){
if [[ -n "$PROXY" ]]; then if [[ -n "$PROXY" ]]; then
[[ -n "$1" ]] && pr_warning " $1 " [[ -n "$1" ]] && pr_warning " $1 "
pr_warning "not tested as proxies do not support proxying it" pr_warning "not tested as proxies do not support proxying it"
fileout "HTTP2/ALPN" "WARN" "HTTP/2 was not tested as proxies do not support proxying it" fileout "ALPN" "WARN" "not tested as proxies do not support proxying it"
return 1 return 1
fi fi
if ! "$HAS_ALPN" && "$SSL_NATIVE"; then if ! "$HAS_ALPN" && "$SSL_NATIVE"; then
prln_local_problem "$OPENSSL doesn't support ALPN/HTTP2"; prln_local_problem "$OPENSSL doesn't support ALPN/HTTP2";
fileout "ALPN" "WARN" "HTTP/2 was not tested as $OPENSSL does not support it" fileout "ALPN" "WARN" "not tested as $OPENSSL does not support it"
return 7 return 7
fi fi
return 0 return 0
@ -8031,7 +8043,7 @@ run_alpn() {
# only h2 is what browser need to use HTTP/2.0 and brings a security benefit # only h2 is what browser need to use HTTP/2.0 and brings a security benefit
if [[ "$proto" == "h2" ]]; then if [[ "$proto" == "h2" ]]; then
pr_svrty_good "$proto" pr_svrty_good "$proto"
fileout "$jsonID" "OK" "$proto" fileout "${jsonID}_HTTP2" "OK" "$proto"
else else
out "$proto" out "$proto"
alpn_finding+="$proto" alpn_finding+="$proto"
@ -12907,8 +12919,6 @@ run_logjam() {
ret=3 # no DH key detected ret=3 # no DH key detected
fi fi
# now the final verdict
# we only use once the color here on the screen, so screen and fileout SEEM to be inconsistent
if "$vuln_exportdh_ciphers"; then if "$vuln_exportdh_ciphers"; then
pr_svrty_high "VULNERABLE (NOT ok):"; out " uses DH EXPORT ciphers" pr_svrty_high "VULNERABLE (NOT ok):"; out " uses DH EXPORT ciphers"
fileout "$jsonID" "HIGH" "VULNERABLE, uses DH EXPORT ciphers" "$cve" "$cwe" "$hint" fileout "$jsonID" "HIGH" "VULNERABLE, uses DH EXPORT ciphers" "$cve" "$cwe" "$hint"
@ -12920,23 +12930,23 @@ run_logjam() {
# now size matters -- i.e. the bit size ;-) # now size matters -- i.e. the bit size ;-)
if [[ $len_dh_p -le 512 ]]; then if [[ $len_dh_p -le 512 ]]; then
pr_svrty_critical "VULNERABLE (NOT ok):"; out " common prime "; pr_italic "$comment"; out " detected ($len_dh_p bits)" pr_svrty_critical "VULNERABLE (NOT ok):"; out " common prime "; pr_italic "$comment"; out " detected ($len_dh_p bits)"
fileout "$jsonID2" "CRITICAL" "common prime \"$comment\" detected" fileout "$jsonID2" "CRITICAL" "$comment"
elif [[ $len_dh_p -le 1024 ]]; then elif [[ $len_dh_p -le 1024 ]]; then
pr_svrty_high "VULNERABLE (NOT ok):"; out " common prime "; pr_italic "$comment"; out " detected ($len_dh_p bits)" pr_svrty_high "VULNERABLE (NOT ok):"; out " common prime "; pr_italic "$comment"; out " detected ($len_dh_p bits)"
fileout "$jsonID2" "HIGH" "common prime \"$comment\" detected" fileout "$jsonID2" "HIGH" "$comment"
elif [[ $len_dh_p -le 1536 ]]; then elif [[ $len_dh_p -le 1536 ]]; then
pr_svrty_medium "common prime with $len_dh_p bits detected: "; pr_italic "$comment" pr_svrty_medium "common prime with $len_dh_p bits detected: "; pr_italic "$comment"
fileout "$jsonID2" "MEDIUM" "common prime \"$comment\" detected" fileout "$jsonID2" "MEDIUM" "$comment"
elif [[ $len_dh_p -le 2048 ]]; then elif [[ $len_dh_p -le 2048 ]]; then
pr_svrty_low "common prime with $len_dh_p bits detected: "; pr_italic "$comment" pr_svrty_low "common prime with $len_dh_p bits detected: "; pr_italic "$comment"
fileout "$jsonID_common primes" "LOW" "common prime \"$comment\" detected" fileout "$jsonID_common primes" "LOW" "$comment"
else else
out "common prime with $len_dh_p bits detected: "; pr_italic "$comment" out "common prime with $len_dh_p bits detected: "; pr_italic "$comment"
fileout "$jsonID2" "INFO" "common prime \"$comment\" detected" fileout "$jsonID2" "INFO" "$comment"
fi fi
elif [[ $ret -eq 0 ]]; then elif [[ $ret -eq 0 ]]; then
out " no common primes detected" out " no common primes detected"
fileout "$jsonID2" "INFO" "no common primes detected" fileout "$jsonID2" "INFO" "--"
elif [[ $ret -eq 7 ]]; then elif [[ $ret -eq 7 ]]; then
out "FIXME 1" out "FIXME 1"
fi fi
@ -12945,16 +12955,16 @@ run_logjam() {
# now size matters -- i.e. the bit size ;-) # now size matters -- i.e. the bit size ;-)
if [[ $len_dh_p -le 512 ]]; then if [[ $len_dh_p -le 512 ]]; then
pr_svrty_critical "VULNERABLE (NOT ok):" ; out " uses common prime "; pr_italic "$comment"; out " ($len_dh_p bits)" pr_svrty_critical "VULNERABLE (NOT ok):" ; out " uses common prime "; pr_italic "$comment"; out " ($len_dh_p bits)"
fileout "$jsonID2" "CRITICAL" "common prime \"$comment\" detected" fileout "$jsonID2" "CRITICAL" "\"$comment\""
elif [[ $len_dh_p -le 1024 ]]; then elif [[ $len_dh_p -le 1024 ]]; then
pr_svrty_high "VULNERABLE (NOT ok):"; out " common prime "; pr_italic "$comment"; out " detected ($len_dh_p bits)" pr_svrty_high "VULNERABLE (NOT ok):"; out " common prime "; pr_italic "$comment"; out " detected ($len_dh_p bits)"
fileout "$jsonID2" "HIGH" "common prime \"$comment\" detected" fileout "$jsonID2" "HIGH" "\"comment\""
elif [[ $len_dh_p -le 1536 ]]; then elif [[ $len_dh_p -le 1536 ]]; then
pr_svrty_medium "Common prime with $len_dh_p bits detected: "; pr_italic "$comment" pr_svrty_medium "Common prime with $len_dh_p bits detected: "; pr_italic "$comment"
fileout "$jsonID2" "MEDIUM" "common prime \"$comment\" detected" fileout "$jsonID2" "MEDIUM" "\"$comment\""
elif [[ $len_dh_p -le 2048 ]]; then elif [[ $len_dh_p -le 2048 ]]; then
pr_svrty_low "Common prime with $len_dh_p bits detected: "; pr_italic "$comment" pr_svrty_low "Common prime with $len_dh_p bits detected: "; pr_italic "$comment"
fileout "$jsonID2" "LOW" "common prime \"$comment\" detected" fileout "$jsonID2" "LOW" "\"$comment\""
else else
out "Common prime with $len_dh_p bits detected: "; pr_italic "$comment" out "Common prime with $len_dh_p bits detected: "; pr_italic "$comment"
fileout "$jsonID2" "INFO" "common prime \"$comment\" detected" fileout "$jsonID2" "INFO" "common prime \"$comment\" detected"
@ -12966,12 +12976,12 @@ run_logjam() {
pr_svrty_good "not vulnerable (OK):"; out " no DH EXPORT ciphers${addtl_warning}" pr_svrty_good "not vulnerable (OK):"; out " no DH EXPORT ciphers${addtl_warning}"
fileout "$jsonID" "OK" "not vulnerable, no DH EXPORT ciphers,$addtl_warning" "$cve" "$cwe" fileout "$jsonID" "OK" "not vulnerable, no DH EXPORT ciphers,$addtl_warning" "$cve" "$cwe"
out ", no DH key detected" out ", no DH key detected"
fileout "$jsonID2" "OK" "no DH key detected" fileout "$jsonID2" "OK" "no DH key"
elif [[ $ret -eq 0 ]]; then elif [[ $ret -eq 0 ]]; then
pr_svrty_good "not vulnerable (OK):"; out " no DH EXPORT ciphers${addtl_warning}" pr_svrty_good "not vulnerable (OK):"; out " no DH EXPORT ciphers${addtl_warning}"
fileout "$jsonID" "OK" "not vulnerable, no DH EXPORT ciphers,$addtl_warning" "$cve" "$cwe" fileout "$jsonID" "OK" "not vulnerable, no DH EXPORT ciphers,$addtl_warning" "$cve" "$cwe"
out ", no common primes detected" out ", no common primes detected"
fileout "$jsonID2" "OK" "no common primes detected" fileout "$jsonID2" "OK" "--"
elif [[ $ret -eq 7 ]]; then elif [[ $ret -eq 7 ]]; then
pr_svrty_good "partly not vulnerable:"; out " no DH EXPORT ciphers${addtl_warning}" pr_svrty_good "partly not vulnerable:"; out " no DH EXPORT ciphers${addtl_warning}"
fileout "$jsonID" "OK" "not vulnerable, no DH EXPORT ciphers,$addtl_warning" "$cve" "$cwe" fileout "$jsonID" "OK" "not vulnerable, no DH EXPORT ciphers,$addtl_warning" "$cve" "$cwe"
@ -16765,10 +16775,11 @@ reset_hostdepended_vars() {
# #
stopwatch() { stopwatch() {
local new_delta local new_delta
local column=$((COLUMNS - 0)) # for future adjustments
"$MEASURE_TIME" || return "$MEASURE_TIME" || return
new_delta=$(( $(date +%s) - LAST_TIME )) new_delta=$(( $(date +%s) - LAST_TIME ))
printf "%${COLUMNS}s" "$new_delta" printf "%${column}s" "$new_delta"
[[ -e "$MEASURE_TIME_FILE" ]] && echo "$1 : $new_delta " >> "$MEASURE_TIME_FILE" [[ -e "$MEASURE_TIME_FILE" ]] && echo "$1 : $new_delta " >> "$MEASURE_TIME_FILE"
LAST_TIME=$(( new_delta + LAST_TIME )) LAST_TIME=$(( new_delta + LAST_TIME ))
} }
@ -16790,6 +16801,7 @@ lets_roll() {
nodeip_to_proper_ip6 nodeip_to_proper_ip6
reset_hostdepended_vars reset_hostdepended_vars
determine_rdns # Returns always zero or has already exited if fatal error occured determine_rdns # Returns always zero or has already exited if fatal error occured
stopwatch determine_rdns
((SERVER_COUNTER++)) ((SERVER_COUNTER++))
determine_service "$1" # STARTTLS service? Other will be determined here too. Returns always 0 or has already exited if fatal error occured determine_service "$1" # STARTTLS service? Other will be determined here too. Returns always 0 or has already exited if fatal error occured
@ -16892,6 +16904,7 @@ lets_roll() {
RET=0 # this is a global as we can have a function main(), see #705. Should we toss then all local $ret? RET=0 # this is a global as we can have a function main(), see #705. Should we toss then all local $ret?
ip="" ip=""
stopwatch start
lets_roll init lets_roll init
initialize_globals initialize_globals
@ -16908,8 +16921,8 @@ lets_roll() {
set_color_functions set_color_functions
maketempf maketempf
find_openssl_binary find_openssl_binary
prepare_debug prepare_debug ; stopwatch parse
prepare_arrays prepare_arrays ; stopwatch prepare_arrays
mybanner mybanner
check_proxy check_proxy
check4openssl_oldfarts check4openssl_oldfarts