add caching of intermediate CA certificates
This commit is contained in:
parent
81a8ac0253
commit
605a1b85fe
94
cipherscan
94
cipherscan
|
@ -57,7 +57,7 @@ ratelimit() {
|
||||||
}
|
}
|
||||||
|
|
||||||
usage() {
|
usage() {
|
||||||
echo -e "usage: $0 [-a|--allciphers] [-b|--benchmark] [--capath directory] [-d|--delay seconds] [-D|--debug] [-j|--json] [-v|--verbose] [-o|--openssl file] [openssl s_client args] <target:port>
|
echo -e "usage: $0 [-a|--allciphers] [-b|--benchmark] [--capath directory] [--saveca] [-d|--delay seconds] [-D|--debug] [-j|--json] [-v|--verbose] [-o|--openssl file] [openssl s_client args] <target:port>
|
||||||
usage: $0 -h|--help
|
usage: $0 -h|--help
|
||||||
|
|
||||||
$0 attempts to connect to a target site using all the ciphersuites it knows.
|
$0 attempts to connect to a target site using all the ciphersuites it knows.
|
||||||
|
@ -71,7 +71,8 @@ Use one of the options below:
|
||||||
|
|
||||||
-a | --allciphers Test all known ciphers individually at the end.
|
-a | --allciphers Test all known ciphers individually at the end.
|
||||||
-b | --benchmark Activate benchmark mode.
|
-b | --benchmark Activate benchmark mode.
|
||||||
--capath use CAs from directory
|
--capath use CAs from directory (must be in OpenSSL CAdir format)
|
||||||
|
--saveca save intermediate certificates in CA directory
|
||||||
-d | --delay Pause for n seconds between connections
|
-d | --delay Pause for n seconds between connections
|
||||||
-D | --debug Output ALL the information.
|
-D | --debug Output ALL the information.
|
||||||
-h | --help Shows this help text.
|
-h | --help Shows this help text.
|
||||||
|
@ -99,6 +100,23 @@ debug(){
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
c_hash() {
|
||||||
|
local h=$(${OPENSSLBIN} x509 -hash -noout -in "$1/$2" 2>/dev/null)
|
||||||
|
for num in $(seq 0 100); do
|
||||||
|
if [[ $1/${h}.${num} -ef $2 ]]; then
|
||||||
|
# file already linked, ignore
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
if [[ ! -e $1/${h}.${num} ]]; then
|
||||||
|
# file doesn't exist, create a link
|
||||||
|
pushd "$1" > /dev/null
|
||||||
|
ln -s "$2" "${h}.${num}"
|
||||||
|
popd > /dev/null
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
# Connect to a target host with the selected ciphersuite
|
# Connect to a target host with the selected ciphersuite
|
||||||
test_cipher_on_target() {
|
test_cipher_on_target() {
|
||||||
local sslcommand=$@
|
local sslcommand=$@
|
||||||
|
@ -107,6 +125,7 @@ test_cipher_on_target() {
|
||||||
protocols=""
|
protocols=""
|
||||||
pfs=""
|
pfs=""
|
||||||
previous_cipher=""
|
previous_cipher=""
|
||||||
|
certificates=""
|
||||||
for tls_version in "-ssl2" "-ssl3" "-tls1" "-tls1_1" "-tls1_2"
|
for tls_version in "-ssl2" "-ssl3" "-tls1" "-tls1_1" "-tls1_2"
|
||||||
do
|
do
|
||||||
# sslv2 client hello doesn't support SNI extension
|
# sslv2 client hello doesn't support SNI extension
|
||||||
|
@ -154,6 +173,63 @@ test_cipher_on_target() {
|
||||||
current_sigalg=None
|
current_sigalg=None
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# collect certificate data
|
||||||
|
current_certificates=""
|
||||||
|
local certificate_count=$(grep --count -- '-----END CERTIFICATE-----'\
|
||||||
|
<<<"$tmp")
|
||||||
|
debug "server presented $certificate_count certificates"
|
||||||
|
local i
|
||||||
|
for ((i=0; i<$certificate_count; i=i+1 )); do
|
||||||
|
|
||||||
|
# extract i'th certificate
|
||||||
|
local cert=$(awk -v i=$i 'split_after == 1 {n++;split_after=0}
|
||||||
|
/-----END CERTIFICATE-----/ {split_after=1}
|
||||||
|
{if (n == i) print }
|
||||||
|
' <<<"$tmp")
|
||||||
|
|
||||||
|
# compute sha256 fingerprint of the certificate
|
||||||
|
local sha256sum=$(${OPENSSLBIN} x509 -outform DER <<<"$cert" 2>/dev/null |\
|
||||||
|
${OPENSSLBIN} dgst -sha256 -r 2>/dev/null| awk '{print $1}')
|
||||||
|
|
||||||
|
# check if it is a CA certificate
|
||||||
|
local isCA="False"
|
||||||
|
if ${OPENSSLBIN} x509 -noout -text <<<"$cert" 2>/dev/null |\
|
||||||
|
grep 'CA:TRUE' >/dev/null; then
|
||||||
|
isCA="True"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# build trust source for certificate verification
|
||||||
|
local trust_source=()
|
||||||
|
if [[ -n $CAPATH ]]; then
|
||||||
|
trust_source=("-CApath" "$CAPATH")
|
||||||
|
elif [[ -e $CACERTS ]]; then
|
||||||
|
trust_source=("-CAfile" "$CACERTS")
|
||||||
|
fi
|
||||||
|
|
||||||
|
# check if the certificate is actually trusted (server may present
|
||||||
|
# unrelated certificates that are not trusted (including self
|
||||||
|
# signed ones)
|
||||||
|
if ${OPENSSLBIN} verify "${trust_source[@]}" \
|
||||||
|
-untrusted <(echo "$tmp") <(echo "$cert") 2>/dev/null | \
|
||||||
|
grep 'OK$' >/dev/null; then
|
||||||
|
|
||||||
|
# if the certificate is an intermediate CA it may be useful
|
||||||
|
# for connecting to servers that are misconfigured so save it
|
||||||
|
if [[ -n $CAPATH ]] && [[ $SAVECA == "True" ]] && [[ $isCA == "True" ]]; then
|
||||||
|
if [[ ! -e "$CAPATH/${sha256sum}.pem" ]]; then
|
||||||
|
echo "$cert" > "$CAPATH/${sha256sum}.pem"
|
||||||
|
c_hash "$CAPATH" "${sha256sum}.pem"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
# save the sha sum for reporting
|
||||||
|
if [ -n "${current_certificates}" ]; then
|
||||||
|
current_certificates+=","
|
||||||
|
fi
|
||||||
|
current_certificates+="\"${sha256sum}\""
|
||||||
|
done
|
||||||
|
debug "current_certificates: $current_certificates"
|
||||||
|
|
||||||
# parsing finished, report result
|
# parsing finished, report result
|
||||||
if [[ -z "$current_protocol" || "$current_cipher" == '(NONE)' ]]; then
|
if [[ -z "$current_protocol" || "$current_cipher" == '(NONE)' ]]; then
|
||||||
# connection failed, try again with next TLS version
|
# connection failed, try again with next TLS version
|
||||||
|
@ -180,6 +256,7 @@ test_cipher_on_target() {
|
||||||
trusted=$current_trusted
|
trusted=$current_trusted
|
||||||
tickethint=$current_tickethint
|
tickethint=$current_tickethint
|
||||||
ocspstaple=$current_ocspstaple
|
ocspstaple=$current_ocspstaple
|
||||||
|
certificates="$current_certificates"
|
||||||
# grab the cipher and PFS key size
|
# grab the cipher and PFS key size
|
||||||
done
|
done
|
||||||
# if cipher is empty, that means none of the TLS version worked with
|
# if cipher is empty, that means none of the TLS version worked with
|
||||||
|
@ -231,7 +308,7 @@ get_cipher_pref() {
|
||||||
|
|
||||||
local sslcommand="$TIMEOUTBIN $TIMEOUT $OPENSSLBIN s_client"
|
local sslcommand="$TIMEOUTBIN $TIMEOUT $OPENSSLBIN s_client"
|
||||||
if [ -n "$CAPATH" ]; then
|
if [ -n "$CAPATH" ]; then
|
||||||
sslcommand+=" -CApath $CAPATH"
|
sslcommand+=" -CApath $CAPATH -showcerts"
|
||||||
elif [ -e $CACERTS ]; then
|
elif [ -e $CACERTS ]; then
|
||||||
sslcommand+=" -CAfile $CACERTS"
|
sslcommand+=" -CAfile $CACERTS"
|
||||||
fi
|
fi
|
||||||
|
@ -243,6 +320,7 @@ get_cipher_pref() {
|
||||||
# If the connection succeeded with the current cipher, benchmark and store
|
# If the connection succeeded with the current cipher, benchmark and store
|
||||||
if [ $success -eq 0 ]; then
|
if [ $success -eq 0 ]; then
|
||||||
cipherspref=("${cipherspref[@]}" "$result")
|
cipherspref=("${cipherspref[@]}" "$result")
|
||||||
|
ciphercertificates=("${ciphercertificates[@]}" "$certificates")
|
||||||
pciph=$(echo $result|awk '{print $1}')
|
pciph=$(echo $result|awk '{print $1}')
|
||||||
get_cipher_pref "!$pciph:$ciphersuite"
|
get_cipher_pref "!$pciph:$ciphersuite"
|
||||||
return 0
|
return 0
|
||||||
|
@ -349,6 +427,9 @@ display_results_in_json() {
|
||||||
echo -n "\"pubkey\":[\"$(echo $cipher|awk '{print $3}'|sed 's/,/","/g')\"],"
|
echo -n "\"pubkey\":[\"$(echo $cipher|awk '{print $3}'|sed 's/,/","/g')\"],"
|
||||||
echo -n "\"sigalg\":[\"$(echo $cipher|awk '{print $4}'|sed 's/,/","/g')\"],"
|
echo -n "\"sigalg\":[\"$(echo $cipher|awk '{print $4}'|sed 's/,/","/g')\"],"
|
||||||
echo -n "\"trusted\":\"$(echo $cipher|awk '{print $5}'|sed 's/,/","/g')\","
|
echo -n "\"trusted\":\"$(echo $cipher|awk '{print $5}'|sed 's/,/","/g')\","
|
||||||
|
if [[ -n $CAPATH ]]; then
|
||||||
|
echo -n "\"certificates\":[${ciphercertificates[$ctr]}],"
|
||||||
|
fi
|
||||||
echo -n "\"ticket_hint\":\"$(echo $cipher|awk '{print $6}')\","
|
echo -n "\"ticket_hint\":\"$(echo $cipher|awk '{print $6}')\","
|
||||||
echo -n "\"ocsp_stapling\":\"$(echo $cipher|awk '{print $7}')\","
|
echo -n "\"ocsp_stapling\":\"$(echo $cipher|awk '{print $7}')\","
|
||||||
pfs=$(echo $cipher|awk '{print $8}')
|
pfs=$(echo $cipher|awk '{print $8}')
|
||||||
|
@ -393,7 +474,7 @@ test_serverside_ordering() {
|
||||||
|
|
||||||
local sslcommand="$TIMEOUTBIN $TIMEOUT $OPENSSLBIN s_client"
|
local sslcommand="$TIMEOUTBIN $TIMEOUT $OPENSSLBIN s_client"
|
||||||
if [ -n "$CAPATH" ]; then
|
if [ -n "$CAPATH" ]; then
|
||||||
sslcommand+=" -CApath $CAPATH"
|
sslcommand+=" -CApath $CAPATH -showcerts"
|
||||||
elif [ -e "$CACERTS" ]; then
|
elif [ -e "$CACERTS" ]; then
|
||||||
sslcommand+=" -CAfile $CACERTS"
|
sslcommand+=" -CAfile $CACERTS"
|
||||||
fi
|
fi
|
||||||
|
@ -453,6 +534,10 @@ do
|
||||||
CAPATH="$2"
|
CAPATH="$2"
|
||||||
shift 2
|
shift 2
|
||||||
;;
|
;;
|
||||||
|
--saveca)
|
||||||
|
SAVECA="True"
|
||||||
|
shift 1
|
||||||
|
;;
|
||||||
--) # End of all options
|
--) # End of all options
|
||||||
shift
|
shift
|
||||||
break
|
break
|
||||||
|
@ -505,6 +590,7 @@ debug "sclientargs: $SCLIENTARGS"
|
||||||
|
|
||||||
|
|
||||||
cipherspref=();
|
cipherspref=();
|
||||||
|
ciphercertificates=()
|
||||||
results=()
|
results=()
|
||||||
|
|
||||||
# Call to the recursive loop that retrieves the cipher preferences
|
# Call to the recursive loop that retrieves the cipher preferences
|
||||||
|
|
Loading…
Reference in New Issue