run_drown() when server has non-RSA certificates

This PR address a problem in `run_drown()` when the server does not support SSLv2, but does support multiple certificates or doesn't have an RSA certificate.

One example of the problem can be seen with www.facebook.com. If `run_server_preferences()` is run before `run_drown()`, then the results of `run_drown()` are:
```
 DROWN (2016-0800, CVE-2016-0703)          not vulnerable on this port (OK)
                                           make sure you don't use this certificate elsewhere with SSLv2 enabled services
                                           https://censys.io/ipv4?q=A626B154CC65634181250B810B1BD4C89EC277CEA08D785EEBE7E768BDA7BB00 SHA256 A3F474FB17509AE6C5B6BA5E46B79E0DE6AF1BF1EEAA040A6114676E714C9965 could help you to find out
```
If only `run_drown()` is performed, then the result is:
```
 DROWN (2016-0800, CVE-2016-0703)          not vulnerable on this port (OK)
                                           make sure you don't use this certificate elsewhere with SSLv2 enabled services
                                           https://censys.io/ipv4?q=A626B154CC65634181250B810B1BD4C89EC277CEA08D785EEBE7E768BDA7BB00 could help you to find out
```
However, A626B154CC65634181250B810B1BD4C89EC277CEA08D785EEBE7E768BDA7BB00 is the fingerprint of Facebook's ECDSA certificate, not its RSA certificate.

In addition, as noted in the "FIXME," `run_drown()` will display the warning "make sure you don't use this certificate elsewhere with SSLv2 enabled services" even if the server doesn't have an RSA certificate, even though SSLv2 can only use RSA certificates.

This PR fixes this issue by only showing the warning if the server has an RSA certificate and by ensuring that the `$cert_fingerprint_sha2` used to construct the "https://censys.io/ipv4?q=..." URL only contains a single SHA256 fingerprint and that it is the fingerprint of the server's RSA certificate.
This commit is contained in:
David Cooper 2016-12-02 10:16:04 -05:00 committed by GitHub
parent b58c48fa3e
commit e7eac77be4
1 changed files with 26 additions and 16 deletions

View File

@ -243,6 +243,7 @@ IPS=""
SERVICE="" # is the server running an HTTP server, SMTP, POP or IMAP?
URI=""
CERT_FINGERPRINT_SHA2=""
RSA_CERT_FINGERPRINT_SHA2=""
SHOW_CENSYS_LINK=${SHOW_CENSYS_LINK:-true}
STARTTLS_PROTOCOL=""
OPTIMAL_PROTO="" # we need this for IIS6 (sigh) and OpenSSL 1.0.2, otherwise some handshakes
@ -4503,7 +4504,7 @@ cipher_pref_check() {
}
# arg1 is proto or empty
# arg1 is OpenSSL s_client parameter or empty
get_host_cert() {
local tmpvar=$TEMPDIR/$FUNCNAME.txt # change later to $TMPFILE
@ -4512,7 +4513,7 @@ get_host_cert() {
awk '/-----BEGIN/,/-----END/ { print $0 }' $tmpvar >$HOSTCERT
return 0
else
pr_warningln "could not retrieve host certificate!"
[[ -z "$1" ]] && pr_warningln "could not retrieve host certificate!"
#fileout "host_certificate" "WARN" "Could not retrieve host certificate!"
return 1
fi
@ -5247,6 +5248,9 @@ certificate_info() {
[[ -z $CERT_FINGERPRINT_SHA2 ]] && \
CERT_FINGERPRINT_SHA2="$cert_fingerprint_sha2" ||
CERT_FINGERPRINT_SHA2="$cert_fingerprint_sha2 $CERT_FINGERPRINT_SHA2"
[[ -z $RSA_CERT_FINGERPRINT_SHA2 ]] && \
( [[ $cert_key_algo = *RSA* ]] || [[ $cert_key_algo = *rsa* ]] ) &&
RSA_CERT_FINGERPRINT_SHA2="$cert_fingerprint_sha2"
out "$indent"; pr_bold " Common Name (CN) "
cnfinding="Common Name (CN) : "
@ -8674,11 +8678,10 @@ run_logjam() {
run_drown() {
local nr_ciphers_detected
local nr_ciphers_detected ret
local spaces=" "
local cert_fingerprint_sha2=""
#FIXME: test for iexistence of RSA key exchange
if [[ $VULN_COUNT -le $VULN_THRESHLD ]]; then
outln
pr_headlineln " Testing for DROWN vulnerability "
@ -8713,22 +8716,29 @@ run_drown() {
;;
*) pr_done_bestln "not vulnerable on this port (OK)"
fileout "drown" "OK" "not vulnerable to DROWN"
outln "$spaces make sure you don't use this certificate elsewhere with SSLv2 enabled services"
if [[ "$DEBUG" -ge 1 ]] || "$SHOW_CENSYS_LINK"; then
# not advertising it as it after 5 tries and account is needed
if [[ -z "$CERT_FINGERPRINT_SHA2" ]]; then
get_host_cert || return 7
cert_fingerprint_sha2="$($OPENSSL x509 -noout -in $HOSTCERT -fingerprint -sha256 2>>$ERRFILE | sed -e 's/^.*Fingerprint=//' -e 's/://g' )"
else
cert_fingerprint_sha2="$CERT_FINGERPRINT_SHA2"
fi
cert_fingerprint_sha2=${cert_fingerprint_sha2/SHA256 /}
outln "$spaces https://censys.io/ipv4?q=$cert_fingerprint_sha2 could help you to find out"
# Any fingerprint that is placed in $RSA_CERT_FINGERPRINT_SHA2 is
# also added to $CERT_FINGERPRINT_SHA2, so if $CERT_FINGERPRINT_SHA2
# is not empty, but $RSA_CERT_FINGERPRINT_SHA2 is empty, then the server
# doesn't have an RSA certificate.
if [[ -z "$CERT_FINGERPRINT_SHA2" ]]; then
get_host_cert "-cipher aRSA"
[[ $? -eq 0 ]] && cert_fingerprint_sha2="$($OPENSSL x509 -noout -in $HOSTCERT -fingerprint -sha256 2>>$ERRFILE | sed -e 's/^.*Fingerprint=//' -e 's/://g' )"
else
cert_fingerprint_sha2="$RSA_CERT_FINGERPRINT_SHA2"
fi
if [[ -n "$cert_fingerprint_sha2" ]]; then
outln "$spaces make sure you don't use this certificate elsewhere with SSLv2 enabled services"
if [[ "$DEBUG" -ge 1 ]] || "$SHOW_CENSYS_LINK"; then
# not advertising it as it after 5 tries and account is needed
cert_fingerprint_sha2=${cert_fingerprint_sha2/SHA256 /}
outln "$spaces https://censys.io/ipv4?q=$cert_fingerprint_sha2 could help you to find out"
fi
fi
ret=0
;;
esac
return $?
return $ret
}