run_rc4() sockets implementation

This PR implements `run_rc4()` in a similar manner to `run_allciphers()` and `run_cipher_per_proto()` (in PR #541). The change doesn't seem to have much of an impact on speed, but when sockets are used it can detect ciphers that aren't locally supported by OpenSSL.
This commit is contained in:
David Cooper 2016-11-29 11:58:49 -05:00 committed by GitHub
parent 071edc794c
commit 01997b8b81
1 changed files with 196 additions and 36 deletions

View File

@ -8822,12 +8822,19 @@ run_lucky13() {
# http://blog.cryptographyengineering.com/2013/03/attack-of-week-rc4-is-kind-of-broken-in.html # http://blog.cryptographyengineering.com/2013/03/attack-of-week-rc4-is-kind-of-broken-in.html
run_rc4() { run_rc4() {
local -i rc4_offered=0 local -i rc4_offered=0
local -i sclient_success local -i nr_ciphers=0 nr_ossl_ciphers=0 nr_nonossl_ciphers=0 ret
local hexcode dash rc4_cipher sslvers kx auth enc mac export local n auth mac export hexc sslv2_ciphers_hex="" sslv2_ciphers_ossl="" s
local rc4_ciphers_list="ECDHE-RSA-RC4-SHA:ECDHE-ECDSA-RC4-SHA:DHE-DSS-RC4-SHA:AECDH-RC4-SHA:ADH-RC4-MD5:ECDH-RSA-RC4-SHA:ECDH-ECDSA-RC4-SHA:RC4-SHA:RC4-MD5:RC4-MD5:RSA-PSK-RC4-SHA:PSK-RC4-SHA:KRB5-RC4-SHA:KRB5-RC4-MD5:RC4-64-MD5:EXP1024-DHE-DSS-RC4-SHA:EXP1024-RC4-SHA:EXP-ADH-RC4-MD5:EXP-RC4-MD5:EXP-RC4-MD5:EXP-KRB5-RC4-SHA:EXP-KRB5-RC4-MD5" local -a normalized_hexcode hexcode ciph sslvers kx enc export2 sigalg ossl_supported
local rc4_ssl2_ciphers_list="RC4-MD5:RC4-64-MD5:EXP-RC4-MD5" local -i i
local rc4_detected="" local -a ciphers_found ciphers_found2 hexcode2 ciph2 sslvers2 rfc_ciph2
local available="" local -i -a index
local dhlen available="" ciphers_to_test supported_sslv2_ciphers addcmd=""
local has_dh_bits="$HAS_DH_BITS" rc4_detected=""
local using_sockets=true
"$SSL_NATIVE" && using_sockets=false
"$FAST" && using_sockets=false
[[ $TLS_NR_CIPHERS == 0 ]] && using_sockets=false
if [[ $VULN_COUNT -le $VULN_THRESHLD ]]; then if [[ $VULN_COUNT -le $VULN_THRESHLD ]]; then
outln outln
@ -8838,62 +8845,215 @@ run_rc4() {
fi fi
pr_bold " RC4"; out " (CVE-2013-2566, CVE-2015-2808) " pr_bold " RC4"; out " (CVE-2013-2566, CVE-2015-2808) "
$OPENSSL s_client -cipher $rc4_ciphers_list $STARTTLS $BUGS -connect $NODEIP:$PORT $PROXY $SNI >$TMPFILE 2>$ERRFILE </dev/null # get a list of all the cipher suites to test
sclient_connect_successful $? $TMPFILE if "$using_sockets" || [[ $OSSL_VER_MAJOR -lt 1 ]]; then
sclient_success=$? for (( i=0; i < TLS_NR_CIPHERS; i++ )); do
if $HAS_SSL2 && [[ $sclient_success -ne 0 ]]; then if [[ "${TLS_CIPHER_RFC_NAME[i]}" =~ "RC4" ]] && ( "$using_sockets" || "${TLS_CIPHER_OSSL_SUPPORTED[i]}" ); then
$OPENSSL s_client -cipher $rc4_ssl2_ciphers_list $STARTTLS $BUGS -connect $NODEIP:$PORT $PROXY -ssl2 >$TMPFILE 2>$ERRFILE </dev/null hexc="$(tolower "${TLS_CIPHER_HEXCODE[i]}")"
sclient_connect_successful $? $TMPFILE ciph[nr_ciphers]="${TLS_CIPHER_OSSL_NAME[i]}"
sclient_success=$? rfc_ciph[nr_ciphers]="${TLS_CIPHER_RFC_NAME[i]}"
sslvers[nr_ciphers]="${TLS_CIPHER_SSLVERS[i]}"
kx[nr_ciphers]="${TLS_CIPHER_KX[i]}"
enc[nr_ciphers]="${TLS_CIPHER_ENC[i]}"
export2[nr_ciphers]="${TLS_CIPHER_EXPORT[i]}"
ciphers_found[nr_ciphers]=false
sigalg[nr_ciphers]=""
ossl_supported[nr_ciphers]="${TLS_CIPHER_OSSL_SUPPORTED[i]}"
if "$using_sockets" && "$WIDE" && ! "$HAS_DH_BITS" &&
( [[ ${kx[nr_ciphers]} == "Kx=ECDH" ]] || [[ ${kx[nr_ciphers]} == "Kx=DH" ]] || [[ ${kx[nr_ciphers]} == "Kx=EDH" ]] ); then
ossl_supported[nr_ciphers]=false
fi
if [[ ${#hexc} -eq 9 ]]; then
hexcode[nr_ciphers]="${hexc:2:2},${hexc:7:2}"
if [[ "${hexc:2:2}" == "00" ]]; then
normalized_hexcode[nr_ciphers]="x${hexc:7:2}"
else
normalized_hexcode[nr_ciphers]="x${hexc:2:2}${hexc:7:2}"
fi
else
hexcode[nr_ciphers]="${hexc:2:2},${hexc:7:2},${hexc:12:2}"
normalized_hexcode[nr_ciphers]="x${hexc:2:2}${hexc:7:2}${hexc:12:2}"
sslv2_ciphers_hex+=", ${hexcode[nr_ciphers]}"
sslv2_ciphers_ossl+=":${ciph[nr_ciphers]}"
fi
nr_ciphers+=1
fi
done
else
while read hexc n ciph[nr_ciphers] sslvers[nr_ciphers] kx[nr_ciphers] auth enc[nr_ciphers] mac export2[nr_ciphers]; do
if [[ "${ciph[nr_ciphers]}" =~ "RC4" ]]; then
ciphers_found[nr_ciphers]=false
if [[ ${#hexc} -eq 9 ]]; then
if [[ "${hexc:2:2}" == "00" ]]; then
normalized_hexcode[nr_ciphers]="$(tolower "x${hexc:7:2}")"
else
normalized_hexcode[nr_ciphers]="$(tolower "x${hexc:2:2}${hexc:7:2}")"
fi
else
normalized_hexcode[nr_ciphers]="$(tolower "x${hexc:2:2}${hexc:7:2}${hexc:12:2}")"
sslv2_ciphers_ossl+=":${ciph[nr_ciphers]}"
fi
sigalg[nr_ciphers]=""
ossl_supported[nr_ciphers]=true
nr_ciphers+=1
fi
done < <($OPENSSL ciphers -V 'ALL:COMPLEMENTOFALL:@STRENGTH' 2>>$ERRFILE)
fi fi
if [[ $sclient_success -eq 0 ]]; then
if "$using_sockets" && [[ -n "$sslv2_ciphers_hex" ]]; then
sslv2_sockets "${sslv2_ciphers_hex:2}" "true"
if [[ $? -eq 3 ]] && [[ "$V2_HELLO_CIPHERSPEC_LENGTH" -ne 0 ]]; then
supported_sslv2_ciphers="$(grep "Supported cipher: " "$TEMPDIR/$NODEIP.parse_sslv2_serverhello.txt")"
"$WIDE" && "$SHOW_SIGALGO" && s="$($OPENSSL x509 -noout -text -in "$HOSTCERT" | awk -F':' '/Signature Algorithm/ { print $2 }' | head -1)"
for (( i=0 ; i<nr_ciphers; i++ )); do
if [[ "${sslvers[i]}" == "SSLv2" ]] && [[ "$supported_sslv2_ciphers" =~ "${normalized_hexcode[i]}" ]]; then
ciphers_found[i]=true
"$WIDE" && "$SHOW_SIGALGO" && sigalg[i]="$s"
rc4_offered=1
fi
done
fi
elif "$HAS_SSL2" && [[ -n "$sslv2_ciphers_ossl" ]]; then
$OPENSSL s_client -cipher "${sslv2_ciphers_ossl:1}" $STARTTLS $BUGS -connect $NODEIP:$PORT $PROXY -ssl2 >$TMPFILE 2>$ERRFILE </dev/null
sclient_connect_successful "$?" "$TMPFILE"
if [[ "$?" -eq 0 ]]; then
supported_sslv2_ciphers="$(grep -A 4 "Ciphers common between both SSL endpoints:" $TMPFILE)"
"$WIDE" && "$SHOW_SIGALGO" && s="$($OPENSSL x509 -noout -text -in $TMPFILE | awk -F':' '/Signature Algorithm/ { print $2 }' | head -1)"
for (( i=0 ; i<nr_ciphers; i++ )); do
if [[ "${sslvers[i]}" == "SSLv2" ]] && [[ "$supported_sslv2_ciphers" =~ "${ciph[i]}" ]]; then
ciphers_found[i]=true
"$WIDE" && "$SHOW_SIGALGO" && sigalg[i]="$s"
rc4_offered=1
fi
done
fi
fi
for (( i=0; i < nr_ciphers; i++ )); do
if "${ossl_supported[i]}" && [[ "${sslvers[i]}" != "SSLv2" ]]; then
ciphers_found2[nr_ossl_ciphers]=false
sslvers2[nr_ossl_ciphers]="${sslvers[i]}"
ciph2[nr_ossl_ciphers]="${ciph[i]}"
index[nr_ossl_ciphers]=$i
nr_ossl_ciphers+=1
fi
done
"$HAS_NO_SSL2" && addcmd="-no_ssl2"
for (( success=0; success==0 ; 1 )); do
ciphers_to_test=""
for (( i=0; i < nr_ossl_ciphers; i++ )); do
! "${ciphers_found2[i]}" && ciphers_to_test+=":${ciph2[i]}"
done
success=1
if [[ -n "$ciphers_to_test" ]]; then
$OPENSSL s_client $addcmd -cipher "${ciphers_to_test:1}" $STARTTLS $BUGS -connect $NODEIP:$PORT $PROXY $SNI >$TMPFILE 2>$ERRFILE </dev/null
sclient_connect_successful "$?" "$TMPFILE"
if [[ "$?" -eq 0 ]]; then
cipher=$(awk '/Cipher *:/ { print $3 }' $TMPFILE)
if [[ -n "$cipher" ]]; then
success=0
rc4_offered=1
for (( i=0; i < nr_ossl_ciphers; i++ )); do
[[ "$cipher" == "${ciph2[i]}" ]] && ciphers_found2[i]=true && break
done
i=${index[i]}
ciphers_found[i]=true
if "$WIDE" && ( [[ ${kx[i]} == "Kx=ECDH" ]] || [[ ${kx[i]} == "Kx=DH" ]] || [[ ${kx[i]} == "Kx=EDH" ]] ); then
dhlen=$(read_dhbits_from_file "$TMPFILE" quiet)
kx[i]="${kx[i]} $dhlen"
fi
"$WIDE" && "$SHOW_SIGALGO" && grep -q "\-\-\-\-\-BEGIN CERTIFICATE\-\-\-\-\-" $TMPFILE && \
sigalg[i]="$($OPENSSL x509 -noout -text -in $TMPFILE | awk -F':' '/Signature Algorithm/ { print $2 }' | head -1)"
fi
fi
fi
done
if "$using_sockets"; then
for (( i=0; i < nr_ciphers; i++ )); do
if ! "${ciphers_found[i]}" && [[ "${sslvers[i]}" != "SSLv2" ]]; then
ciphers_found2[nr_nonossl_ciphers]=false
sslvers2[nr_nonossl_ciphers]="${sslvers[i]}"
hexcode2[nr_nonossl_ciphers]="${hexcode[i]}"
rfc_ciph2[nr_nonossl_ciphers]="${rfc_ciph[i]}"
index[nr_nonossl_ciphers]=$i
nr_nonossl_ciphers+=1
fi
done
fi
for (( success=0; success==0 ; 1 )); do
ciphers_to_test=""
for (( i=0; i < nr_nonossl_ciphers; i++ )); do
! "${ciphers_found2[i]}" && ciphers_to_test+=", ${hexcode2[i]}"
done
success=1
if [[ -n "$ciphers_to_test" ]]; then
if "$WIDE" && "$SHOW_SIGALGO"; then
tls_sockets "03" "${ciphers_to_test:2}, 00,ff" "all"
else
tls_sockets "03" "${ciphers_to_test:2}, 00,ff" "ephemeralkey"
fi
ret=$?
if [[ $ret -eq 0 ]] || [[ $ret -eq 2 ]]; then
success=0
rc4_offered=1
cipher=$(awk '/Cipher *:/ { print $3 }' "$TEMPDIR/$NODEIP.parse_tls_serverhello.txt")
for (( i=0; i < nr_nonossl_ciphers; i++ )); do
[[ "$cipher" == "${rfc_ciph2[i]}" ]] && ciphers_found2[i]=true && break
done
i=${index[i]}
ciphers_found[i]=true
if "$WIDE" && ( [[ ${kx[i]} == "Kx=ECDH" ]] || [[ ${kx[i]} == "Kx=DH" ]] || [[ ${kx[i]} == "Kx=EDH" ]] ); then
dhlen=$(read_dhbits_from_file "$TEMPDIR/$NODEIP.parse_tls_serverhello.txt" quiet)
kx[i]="${kx[i]} $dhlen"
fi
"$WIDE" && "$SHOW_SIGALGO" && [[ -r "$HOSTCERT" ]] && \
sigalg[i]="$($OPENSSL x509 -noout -text -in "$HOSTCERT" | awk -F':' '/Signature Algorithm/ { print $2 }' | head -1)"
fi
fi
done
if [[ $rc4_offered -eq 1 ]]; then
"$WIDE" || pr_svrty_high "VULNERABLE (NOT ok): " "$WIDE" || pr_svrty_high "VULNERABLE (NOT ok): "
rc4_offered=1
if "$WIDE"; then if "$WIDE"; then
outln "\n" outln "\n"
neat_header neat_header
fi fi
while read hexcode dash rc4_cipher sslvers kx auth enc mac; do for (( i=0 ; i<nr_ciphers; i++ )); do
if [[ "$sslvers" == "SSLv2" ]]; then if ! "${ciphers_found[i]}" && ! "$SHOW_EACH_C"; then
$OPENSSL s_client -cipher $rc4_cipher $STARTTLS $BUGS -connect $NODEIP:$PORT $PROXY -ssl2 </dev/null >$TMPFILE 2>$ERRFILE
else
$OPENSSL s_client -cipher $rc4_cipher $STARTTLS $BUGS -connect $NODEIP:$PORT $PROXY $SNI </dev/null >$TMPFILE 2>$ERRFILE
fi
sclient_connect_successful $? $TMPFILE
sclient_success=$? # here we may have a fp with openssl < 1.0, TBC
if [[ $sclient_success -ne 0 ]] && ! "$SHOW_EACH_C"; then
continue # no successful connect AND not verbose displaying each cipher continue # no successful connect AND not verbose displaying each cipher
fi fi
if "$WIDE"; then if "$WIDE"; then
#FIXME: JSON+CSV in wide mode is missing #FIXME: JSON+CSV in wide mode is missing
normalize_ciphercode "$hexcode" neat_list "${normalized_hexcode[i]}" "${ciph[i]}" "${kx[i]}" "${enc[i]}"
neat_list "$HEXC" "$rc4_cipher" "$kx" "$enc"
if "$SHOW_EACH_C"; then if "$SHOW_EACH_C"; then
if [[ $sclient_success -eq 0 ]]; then if "${ciphers_found[i]}"; then
pr_svrty_high "available" pr_svrty_high "available"
else else
out "not a/v" out "not a/v"
fi fi
else
rc4_offered=1
out
fi fi
outln outln "${sigalg[i]}"
else elif "${ciphers_found[i]}"; then
[[ $sclient_success -eq 0 ]] && pr_svrty_high "$rc4_cipher " pr_svrty_high "${ciph[i]} "
fi fi
[[ $sclient_success -eq 0 ]] && rc4_detected+="$rc4_cipher " "${ciphers_found[i]}" && rc4_detected+="${ciph[i]} "
done < <($OPENSSL ciphers -V $rc4_ciphers_list:@STRENGTH) done
outln outln
"$WIDE" && pr_svrty_high "VULNERABLE (NOT ok)" "$WIDE" && pr_svrty_high "VULNERABLE (NOT ok)"
fileout "rc4" "HIGH" "RC4 (CVE-2013-2566, CVE-2015-2808) : VULNERABLE (NOT ok) Detected ciphers: $rc4_detected" fileout "rc4" "HIGH" "RC4 (CVE-2013-2566, CVE-2015-2808) : VULNERABLE (NOT ok) Detected ciphers: $rc4_detected"
elif [[ $nr_ciphers -eq 0 ]]; then
local_problem_ln "No RC4 Ciphers configured in $OPENSSL"
fileout "rc4" "WARN" "RC4 ciphers not supported by local OpenSSL ($OPENSSL)"
else else
pr_done_goodln "no RC4 ciphers detected (OK)" pr_done_goodln "no RC4 ciphers detected (OK)"
fileout "rc4" "OK" "RC4 (CVE-2013-2566, CVE-2015-2808) : not vulnerable (OK)" fileout "rc4" "OK" "RC4 (CVE-2013-2566, CVE-2015-2808) : not vulnerable (OK)"
rc4_offered=0
fi fi
outln outln
"$using_sockets" && HAS_DH_BITS="$has_dh_bits"
tmpfile_handle $FUNCNAME.txt tmpfile_handle $FUNCNAME.txt
return $rc4_offered return $rc4_offered
} }