Fixed the encoding for root/intermediate CAs now.
This commit is contained in:
parent
e280cac2af
commit
07f91a54bf
173
testssl.sh
173
testssl.sh
|
@ -1029,104 +1029,124 @@ run_hpkp() {
|
||||||
fileout "hpkp_preload" "INFO" "HPKP header is NOT marked for browser preloading"
|
fileout "hpkp_preload" "INFO" "HPKP header is NOT marked for browser preloading"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Get the pins first
|
||||||
|
pins=$(tr ';' '\n' < $TMPFILE | tr -d ' ' | tr -d '\"' | awk -F'=' '/pin.*=/ { print $2 }')
|
||||||
|
|
||||||
|
|
||||||
|
# Look at the host certificate first
|
||||||
|
# get the key fingerprint from the host certificate
|
||||||
if [[ ! -s "$HOSTCERT" ]]; then
|
if [[ ! -s "$HOSTCERT" ]]; then
|
||||||
get_host_cert || return 1
|
get_host_cert || return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Get the pins first
|
|
||||||
pins=$(tr ';' '\n' < $TMPFILE | tr -d ' ' | tr -d '\"' | awk -F'=' '/pin.*=/ { print $2 }')
|
|
||||||
|
|
||||||
# get the key fingerprint from the host certificate
|
|
||||||
hpkp_key_hostcert="$($OPENSSL x509 -in $HOSTCERT -pubkey -noout | grep -v PUBLIC | \
|
hpkp_key_hostcert="$($OPENSSL x509 -in $HOSTCERT -pubkey -noout | grep -v PUBLIC | \
|
||||||
$OPENSSL base64 -d | $OPENSSL dgst -sha256 -binary | $OPENSSL base64)"
|
$OPENSSL base64 -d | $OPENSSL dgst -sha256 -binary | $OPENSSL base64)"
|
||||||
# compare it with the ones provided in the header
|
|
||||||
for hpkp_key in $(echo "$pins"); do
|
|
||||||
if [[ "$hpkp_key_hostcert" == "$hpkp_key" ]] || [[ "$hpkp_key_hostcert" == "$hpkp_key=" ]]; then
|
# Get keys/hashes from intermediate certificates
|
||||||
out "\n$spaces matching host key: "
|
$OPENSSL s_client -showcerts $STARTTLS $BUGS $PROXY -showcerts -connect $NODEIP:$PORT ${sni[i]} </dev/null >$TMPFILE 2>$ERRFILE
|
||||||
pr_done_good "$hpkp_key"
|
# Place the server's certificate in $HOSTCERT and any intermediate
|
||||||
fileout "hpkp_keymatch" "OK" "Host certificate key matches a key pinned in the HPKP header"
|
# certificates that were provided in $TEMPDIR/intermediatecerts.pem
|
||||||
key_found=true
|
# http://backreference.org/2010/05/09/ocsp-verification-with-openssl/
|
||||||
|
awk -v n=-1 "/Certificate chain/ {start=1}
|
||||||
|
/-----BEGIN CERTIFICATE-----/{ if (start) {inc=1; n++} }
|
||||||
|
inc { print > (\"$TEMPDIR/level\" n \".crt\") }
|
||||||
|
/---END CERTIFICATE-----/{ inc=0 }" $TMPFILE
|
||||||
|
nrsaved=$(count_words "$(echo $TEMPDIR/level?.crt 2>/dev/null)")
|
||||||
|
rm $TEMPDIR/level0.crt
|
||||||
|
|
||||||
|
if [[ nrsaved -ge 2 ]]; then
|
||||||
|
echo -n "" > "$TEMPDIR/intermediate.hashes"
|
||||||
|
for cert_fname in $TEMPDIR/level?.crt; do
|
||||||
|
hpkp_key_ca="$($OPENSSL x509 -in "$cert_fname" -pubkey -noout | grep -v PUBLIC | $OPENSSL base64 -d |
|
||||||
|
$OPENSSL dgst -sha256 -binary | $OPENSSL enc -base64)"
|
||||||
|
hpkp_name="$(get_cn_from_cert $cert_fname)"
|
||||||
|
[[ -n $hpkp_name ]] || hpkp_name=$($OPENSSL x509 -in "$cert_fname" -subject -noout | sed 's/^subject= //')
|
||||||
|
echo "$hpkp_key_ca $hpkp_name" >> "$TEMPDIR/intermediate.hashes"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
rm $TEMPDIR/level*.crt
|
||||||
|
|
||||||
|
# Get keys from Root CAs
|
||||||
|
for bundle_fname in $ca_bundles; do
|
||||||
|
local bundle_name=$(basename ${bundle_fname//.pem})
|
||||||
|
if [[ ! -r $bundle_fname ]]; then
|
||||||
|
pr_warningln "\"$bundle_fname\" cannot be found / not readable"
|
||||||
|
return 7
|
||||||
fi
|
fi
|
||||||
debugme out "\n $hpkp_key | $hpkp_key_hostcert"
|
debugme printf -- " %-12s" "${certificate_file[i]}"
|
||||||
|
# Split up the certificate bundle
|
||||||
|
awk -v n=-1 "BEGIN {start=1}
|
||||||
|
/-----BEGIN CERTIFICATE-----/{ if (start) {inc=1; n++} }
|
||||||
|
inc { print >> (\"$TEMPDIR/$bundle_name.\" n \".crt\") ; close (\"$TEMPDIR/$bundle_name.\" n \".crt\") }
|
||||||
|
/---END CERTIFICATE-----/{ inc=0 }" $bundle_fname
|
||||||
|
# Clear temp file
|
||||||
|
echo -n "" > "$TEMPDIR/hashes.$bundle_name"
|
||||||
|
for cert_fname in $TEMPDIR/$bundle_name.*.crt; do
|
||||||
|
hpkp_key_ca="$($OPENSSL x509 -in "$cert_fname" -pubkey -noout | grep -v PUBLIC | $OPENSSL base64 -d |
|
||||||
|
$OPENSSL dgst -sha256 -binary | $OPENSSL enc -base64)"
|
||||||
|
issuer=$(get_cn_from_cert $cert_fname)
|
||||||
|
[[ -n $hpkp_name ]] || hpkp_name=$($OPENSSL x509 -in "$cert_fname" -subject -noout| sed "s/^subject= //")
|
||||||
|
echo "$hpkp_key_ca $bundle_name : $issuer" >> "$TEMPDIR/hashes.$bundle_name"
|
||||||
|
done
|
||||||
done
|
done
|
||||||
|
|
||||||
if ! $key_found ; then
|
pins_match=false
|
||||||
# Get keys from intermediate certificates
|
for hpkp_key in $(echo $pins); do
|
||||||
$OPENSSL s_client -showcerts $STARTTLS $BUGS $PROXY -showcerts -connect $NODEIP:$PORT ${sni[i]} </dev/null >$TMPFILE 2>$ERRFILE
|
key_found=false
|
||||||
# Place the server's certificate in $HOSTCERT and any intermediate
|
|
||||||
# certificates that were provided in $TEMPDIR/intermediatecerts.pem
|
|
||||||
# http://backreference.org/2010/05/09/ocsp-verification-with-openssl/
|
|
||||||
awk -v n=-1 "/Certificate chain/ {start=1}
|
|
||||||
/-----BEGIN CERTIFICATE-----/{ if (start) {inc=1; n++} }
|
|
||||||
inc { print > (\"$TEMPDIR/level\" n \".crt\") }
|
|
||||||
/---END CERTIFICATE-----/{ inc=0 }" $TMPFILE
|
|
||||||
nrsaved=$(count_words "$(echo $TEMPDIR/level?.crt 2>/dev/null)")
|
|
||||||
rm $TEMPDIR/level0.crt
|
|
||||||
|
|
||||||
# Compare them against the hashes found
|
# compare pin against the leaf certificate
|
||||||
if [[ nrsaved -ge 2 ]]; then
|
if [[ "$hpkp_key_hostcert" == "$hpkp_key" ]] || [[ "$hpkp_key_hostcert" == "$hpkp_key=" ]]; then
|
||||||
echo -n "" > "$TEMPDIR/hashes.intermediate"
|
out "\n$spaces Leaf certificate match : "
|
||||||
for cert_fname in $TEMPDIR/level?.crt; do
|
pr_done_good "$hpkp_key"
|
||||||
hpkp_key_ca="$($OPENSSL x509 -in "$cert_fname" -pubkey -noout | grep -v PUBLIC|$OPENSSL dgst -sha256 -binary | $OPENSSL enc -base64)"
|
fileout "hpkp_$hpkp_key" "OK" "PIN $hpkp_key matches the leaf certificate"
|
||||||
issuer="$(get_cn_from_cert $cert_fname)"
|
key_found=true
|
||||||
[[ -n $hpkp_name ]] || hpkp_name=$($OPENSSL x509 -in "$cert_fname" -subject -noout| sed "s/^subject= //")
|
pins_match=true
|
||||||
echo "$hpkp_key_ca $bundle_name $issuer" >> "$TEMPDIR/hashes.intermediate"
|
|
||||||
done
|
|
||||||
for hpkp_key in $(echo $pins); do
|
|
||||||
hpkp_matches=$(grep "$hpkp_key" $TEMPDIR/hashes.intermediate)
|
|
||||||
if [[ -n $hpkp_matches ]]; then
|
|
||||||
# We have a winner!
|
|
||||||
key_found=true
|
|
||||||
out "\n$spaces Intermediate CA match : "
|
|
||||||
pr_done_good "$hpkp_matches"
|
|
||||||
fileout "hpkp_keymatch" "OK" "Intermediate CA key matches a key pinned in the HPKP header\nKey/CA: $hpkp_matches"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
fi
|
fi
|
||||||
fi
|
debugme out "\n $hpkp_key | $hpkp_key_hostcert"
|
||||||
|
|
||||||
if ! $key_found ; then
|
# Check for intermediate match
|
||||||
# Get keys from Root CAs
|
if ! $key_found ; then
|
||||||
for bundle_fname in $ca_bundles; do
|
hpkp_matches=$(grep "$hpkp_key" $TEMPDIR/intermediate.hashes)
|
||||||
local bundle_name=$(basename ${bundle_fname//.pem})
|
if [[ -n $hpkp_matches ]]; then
|
||||||
if [[ ! -r $bundle_fname ]]; then
|
# We have a winner!
|
||||||
pr_warningln "\"$bundle_fname\" cannot be found / not readable"
|
key_found=true
|
||||||
return 7
|
pins_match=true
|
||||||
|
out "\n$spaces Intermediate CA match : "
|
||||||
|
pr_done_good "$hpkp_key"
|
||||||
|
out "\n$spaces $(echo $hpkp_matches|sed "s/^[a-zA-Z0-9\+\/]*=* *//")"
|
||||||
|
fileout "hpkp_$hpkp_key" "OK" "Intermediate CA key matches a key pinned in the HPKP header\nKey/CA: $hpkp_matches"
|
||||||
fi
|
fi
|
||||||
debugme printf -- " %-12s" "${certificate_file[i]}"
|
fi
|
||||||
# Split up the certificate bundle
|
|
||||||
awk -v n=-1 "BEGIN {start=1}
|
if ! $key_found ; then
|
||||||
/-----BEGIN CERTIFICATE-----/{ if (start) {inc=1; n++} }
|
|
||||||
inc { print >> (\"$TEMPDIR/$bundle_name.\" n \".crt\") ; close (\"$TEMPDIR/$bundle_name.\" n \".crt\") }
|
|
||||||
/---END CERTIFICATE-----/{ inc=0 }" $bundle_fname
|
|
||||||
# Clear temp file
|
|
||||||
echo -n "" > "$TEMPDIR/hashes.$bundle_name"
|
|
||||||
for cert_fname in $TEMPDIR/$bundle_name.*.crt; do
|
|
||||||
hpkp_key_ca="$($OPENSSL x509 -in "$cert_fname" -pubkey -noout | grep -v PUBLIC|$OPENSSL dgst -sha256 -binary | $OPENSSL enc -base64)"
|
|
||||||
issuer="$(get_cn_from_cert $cert_fname)"
|
|
||||||
[[ -n $hpkp_name ]] || hpkp_name=$($OPENSSL x509 -in "$cert_fname" -subject -noout| sed "s/^subject= //")
|
|
||||||
echo "$hpkp_key_ca $bundle_name : $issuer" >> "$TEMPDIR/hashes.$bundle_name"
|
|
||||||
done
|
|
||||||
done
|
|
||||||
for hpkp_key in $(echo $pins); do
|
|
||||||
hpkp_matches=$(grep -h "$hpkp_key" $TEMPDIR/hashes.*)
|
hpkp_matches=$(grep -h "$hpkp_key" $TEMPDIR/hashes.*)
|
||||||
if [[ -n $hpkp_matches ]]; then
|
if [[ -n $hpkp_matches ]]; then
|
||||||
# We have a winner!
|
# We have a winner!
|
||||||
key_found=true
|
key_found=true
|
||||||
|
pins_match=true
|
||||||
out "\n$spaces Root CA match : "
|
out "\n$spaces Root CA match : "
|
||||||
pr_done_goodln "$hpkp_key"
|
pr_done_good "$hpkp_key"
|
||||||
#out "$hpkp_matches"
|
echo "$hpkp_matches"|sort -u|while read line; do
|
||||||
|
out "\n$spaces $(echo $line |sed "s/^[a-zA-Z0-9\+\/]*=* *//")"
|
||||||
fileout "hpkp_keymatch" "OK" "Root CA key matches a key pinned in the HPKP header\nKey/OS/CA: $hpkp_matches"
|
done
|
||||||
|
fileout "hpkp_$hpkp_key" "OK" "Root CA key matches a key pinned in the HPKP header\nKey/OS/CA: $hpkp_matches"
|
||||||
fi
|
fi
|
||||||
done
|
fi
|
||||||
fi
|
|
||||||
|
if ! $key_found ; then
|
||||||
|
# Houston we may have a problem
|
||||||
|
out "\n$spaces Unmatched key : "
|
||||||
|
pr_warning "$hpkp_key"
|
||||||
|
out " ( You can ignore this if this is a backup pin of your leaf certificate )"
|
||||||
|
fileout "hpkp_$hpkp_key" "WARN" "PIN $hpkp_key doesn't matchyour leaf certificate or and intermediate or known root CA\nThis could be ok if it is a backup pin for a leaf certificate"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
# If all else fails...
|
# If all else fails...
|
||||||
if ! $key_found ; then
|
if ! $pins_match ; then
|
||||||
pr_svrty_high " No matching key for pins found "
|
pr_svrty_high " No matching key for pins found "
|
||||||
out "(CAs pinned? -- not checked for yet)"
|
fileout "hpkp_keymatch" "NOT ok" "None of the HPKP PINS match your leaf certificate, intermediate CA or known root CAs. You may have bricked this site"
|
||||||
fileout "hpkp_keymatch" "DEBUG" "The TLS key does not match any key pinned in the HPKP header. If you pinned a CA key you can ignore this"
|
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
out "--"
|
out "--"
|
||||||
|
@ -3858,6 +3878,7 @@ get_cn_from_cert() {
|
||||||
# for e.g. russian sites -esc_msb,utf8 works in an UTF8 terminal -- any way to check platform indepedent?
|
# for e.g. russian sites -esc_msb,utf8 works in an UTF8 terminal -- any way to check platform indepedent?
|
||||||
# see x509(1ssl):
|
# see x509(1ssl):
|
||||||
subject="$($OPENSSL x509 -in $1 -noout -subject -nameopt multiline,-align,sname,-esc_msb,utf8,-space_eq 2>>$ERRFILE)"
|
subject="$($OPENSSL x509 -in $1 -noout -subject -nameopt multiline,-align,sname,-esc_msb,utf8,-space_eq 2>>$ERRFILE)"
|
||||||
|
#echo "$subject" | sed "s/^.*CN\=//" | sed "s/\/.*$//"
|
||||||
echo "$(awk -F'=' '/CN=/ { print $2 }' <<< "$subject")"
|
echo "$(awk -F'=' '/CN=/ { print $2 }' <<< "$subject")"
|
||||||
return $?
|
return $?
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue