mirror of
https://github.com/mozilla/cipherscan.git
synced 2025-06-07 19:43:40 +02:00
Merge ed34c0e046
into ded65c40df
This commit is contained in:
commit
ed50f3c400
10
README.md
10
README.md
@ -8,15 +8,18 @@ On Linux x86_64 run: ./cipherscan www.google.com:443
|
|||||||
On any other *nix or *tux run: ./cipherscan -o /path/to/openssl www.google.com:443
|
On any other *nix or *tux run: ./cipherscan -o /path/to/openssl www.google.com:443
|
||||||
and watch.
|
and watch.
|
||||||
|
|
||||||
The newer your version of openssl, the better results you'll get. Versions
|
On FreeBSD, you will need the following ports: textproc/gnugrep and sysutils/coreutils
|
||||||
of OpenSSL below 1.0.1 don't support TLS1.2 ciphers, elliptic curves, etc... Build your own or test what your system's OpenSSL supports.
|
|
||||||
|
The newer your version of openssl, the better results you'll get. Versions of OpenSSL below 1.0.1 don't support TLS1.2 ciphers, elliptic curves, etc...
|
||||||
|
Version 1.0.2 gives extra information about the ciphers used for the key exchange.
|
||||||
|
Build your own or test what your system's OpenSSL supports.
|
||||||
|
|
||||||
Cipherscan should work fine on Linux, Mac OS X, Solaris, Illumos, SmartOS, OpenIndiana if you specify a an openssl binary with -o.
|
Cipherscan should work fine on Linux, Mac OS X, Solaris, Illumos, SmartOS, OpenIndiana if you specify a an openssl binary with -o.
|
||||||
|
|
||||||
Build OpenSSL with ChaCha20-Poly1305 support (Optional)
|
Build OpenSSL with ChaCha20-Poly1305 support (Optional)
|
||||||
-------------------------------------------------------
|
-------------------------------------------------------
|
||||||
|
|
||||||
The OpenSSL binary in this repository is built for 64bit Linux. If you wish to build a version with the same features for your own platform, [the snapshot from the OpenSSL gitweb view](http://git.openssl.org/gitweb/?p=openssl.git;a=tree;h=161b23361778c155f9c174694b1db2506a2e0b52;hb=9a8646510b) and build it like this:
|
The OpenSSL binary in this repository is built for 64bit Linux. If you wish to build a version with the same features for your own platform, you can use [this snapshot from the OpenSSL gitweb view](http://git.openssl.org/gitweb/?p=openssl.git;a=tree;h=161b23361778c155f9c174694b1db2506a2e0b52;hb=9a8646510b) or [this Github repository](https://github.com/PeterMosmans/openssl) and build it like this:
|
||||||
|
|
||||||
```
|
```
|
||||||
./config no-shared
|
./config no-shared
|
||||||
@ -226,3 +229,4 @@ Contributors
|
|||||||
* Pepi Zawodsky <git@maclemon.at>
|
* Pepi Zawodsky <git@maclemon.at>
|
||||||
* Michael Zeltner <m@niij.org>
|
* Michael Zeltner <m@niij.org>
|
||||||
* Simon Deziel <simon.deziel@gmail.com>
|
* Simon Deziel <simon.deziel@gmail.com>
|
||||||
|
* Olivier Paroz <opa-github@interfasys.ch>
|
||||||
|
89
cipherscan
89
cipherscan
@ -4,12 +4,22 @@
|
|||||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
# Author: Julien Vehent [:ulfr] - 2013
|
# Author: Julien Vehent [:ulfr] - 2013
|
||||||
|
#
|
||||||
|
# Modified by Olivier Paroz in September 2014
|
||||||
|
#
|
||||||
|
# On FreeBSD, you will need the following ports: textproc/gnugrep and sysutils/coreutils
|
||||||
|
#
|
||||||
|
|
||||||
|
OS=`uname`
|
||||||
DOBENCHMARK=0
|
DOBENCHMARK=0
|
||||||
BENCHMARKITER=30
|
BENCHMARKITER=30
|
||||||
|
TIMEOUTBIN=timeout
|
||||||
|
if [ "${OS}" = "FreeBSD" ]; then
|
||||||
|
TIMEOUTBIN=gtimeout
|
||||||
|
fi
|
||||||
OPENSSLBIN="$(dirname $0)/openssl"
|
OPENSSLBIN="$(dirname $0)/openssl"
|
||||||
if [ -z "$CACERTS" ]; then
|
if [ -z "$CACERTS" ]; then
|
||||||
for f in /etc/pki/tls/certs/ca-bundle.crt /etc/ssl/certs/ca-certificates.crt; do
|
for f in /etc/pki/tls/certs/ca-bundle.crt /etc/ssl/certs/ca-certificates.crt /usr/local/share/certs/ca-root-nss.crt; do
|
||||||
if [ -e "$f" ]; then
|
if [ -e "$f" ]; then
|
||||||
CACERTS="$f"
|
CACERTS="$f"
|
||||||
break
|
break
|
||||||
@ -29,6 +39,7 @@ DELAY=0
|
|||||||
ALLCIPHERS=0
|
ALLCIPHERS=0
|
||||||
OUTPUTFORMAT="terminal"
|
OUTPUTFORMAT="terminal"
|
||||||
TIMEOUT=10
|
TIMEOUT=10
|
||||||
|
SNISCAN=0
|
||||||
|
|
||||||
|
|
||||||
usage() {
|
usage() {
|
||||||
@ -36,7 +47,11 @@ usage() {
|
|||||||
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.
|
||||||
Julien Vehent [:ulfr] - https://github.com/jvehent/cipherscan
|
|
||||||
|
Original script by Julien Vehent. [:ulfr] - https://github.com/jvehent/cipherscan
|
||||||
|
FreeBSD version by Olivier Paroz - https://github.com/oparoz/cipherscan
|
||||||
|
|
||||||
|
On FreeBSD, you will need the following ports on FreeBSD: textproc/gnugrep and sysutils/coreutils
|
||||||
|
|
||||||
Port defaults to 443
|
Port defaults to 443
|
||||||
|
|
||||||
@ -51,6 +66,7 @@ Use one of the options below:
|
|||||||
-h | --help Shows this help text.
|
-h | --help Shows this help text.
|
||||||
-j | --json Output results in JSON format.
|
-j | --json Output results in JSON format.
|
||||||
-o | --openssl path/to/your/openssl binary you want to use.
|
-o | --openssl path/to/your/openssl binary you want to use.
|
||||||
|
-s | --sni Activates SNI
|
||||||
-v | --verbose Increase verbosity.
|
-v | --verbose Increase verbosity.
|
||||||
|
|
||||||
The rest of the arguments will be interpreted as openssl s_client argument.
|
The rest of the arguments will be interpreted as openssl s_client argument.
|
||||||
@ -92,8 +108,13 @@ test_cipher_on_target() {
|
|||||||
fi
|
fi
|
||||||
# filter out the OCSP server certificate
|
# filter out the OCSP server certificate
|
||||||
tmp=$(awk 'BEGIN { pr="yes" } /^======================================/ { if ( pr=="yes" ) pr="no"; else pr="yes" } { if ( pr == "yes" ) print }' <<<"$tmp")
|
tmp=$(awk 'BEGIN { pr="yes" } /^======================================/ { if ( pr=="yes" ) pr="no"; else pr="yes" } { if ( pr == "yes" ) print }' <<<"$tmp")
|
||||||
|
current_certcn=$(grep "subject=" <<<"$tmp"| grep -oP "(?<=CN\=)[^ |\/]+")
|
||||||
|
current_subjaltnames=$(${OPENSSLBIN} x509 -noout -text 2>/dev/null <<<"$tmp"|awk '/X509v3 Subject Alternative Name/ {getline;gsub(/ /, "", $0);print}' | tr -d "DNS:")
|
||||||
current_cipher=$(grep "New, " <<<"$tmp"|awk '{print $5}')
|
current_cipher=$(grep "New, " <<<"$tmp"|awk '{print $5}')
|
||||||
current_pfs=$(grep 'Server Temp Key' <<<"$tmp"|awk '{print $4$5$6$7}')
|
current_pfs=$(grep 'Server Temp Key' <<<"$tmp"|awk '{print $4$5$6$7}')
|
||||||
|
if [ -z $current_pfs ]; then
|
||||||
|
current_pfs="None"
|
||||||
|
fi
|
||||||
current_protocol=$(egrep "^\s+Protocol\s+:" <<<"$tmp"|awk '{print $3}')
|
current_protocol=$(egrep "^\s+Protocol\s+:" <<<"$tmp"|awk '{print $3}')
|
||||||
current_pubkey=$(grep 'Server public key is ' <<<"$tmp"|awk '{print $5}')
|
current_pubkey=$(grep 'Server public key is ' <<<"$tmp"|awk '{print $5}')
|
||||||
if [ -z $current_pubkey ]; then
|
if [ -z $current_pubkey ]; then
|
||||||
@ -131,6 +152,16 @@ test_cipher_on_target() {
|
|||||||
else
|
else
|
||||||
protocols="$protocols,$current_protocol"
|
protocols="$protocols,$current_protocol"
|
||||||
fi
|
fi
|
||||||
|
certcns="$current_certcn"
|
||||||
|
# Let's add the alternative subject names if they exist
|
||||||
|
if [ -n "$current_subjaltnames" ]; then
|
||||||
|
IFS=',' read -ra subjaltnamesarray <<<"$current_subjaltnames"
|
||||||
|
for altname in "${subjaltnamesarray[@]}"; do
|
||||||
|
if [[ "$altname" != "$current_certcn" ]]; then
|
||||||
|
certcns="$certcns,$altname"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
cipher=$current_cipher
|
cipher=$current_cipher
|
||||||
pfs=$current_pfs
|
pfs=$current_pfs
|
||||||
pubkey=$current_pubkey
|
pubkey=$current_pubkey
|
||||||
@ -149,13 +180,13 @@ test_cipher_on_target() {
|
|||||||
|
|
||||||
# if cipher contains NONE, the cipher wasn't accepted
|
# if cipher contains NONE, the cipher wasn't accepted
|
||||||
elif [ "$cipher" == '(NONE) ' ]; then
|
elif [ "$cipher" == '(NONE) ' ]; then
|
||||||
result="$cipher $protocols $pubkey $sigalg $trusted $tickethint $ocspstaple $pfs"
|
result="$cipher $protocols $pubkey $sigalg $trusted $tickethint $ocspstaple $pfs $certcns"
|
||||||
verbose "handshake failed, server returned ciphersuite '$result'"
|
verbose "handshake failed, server returned ciphersuite '$result'"
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
# the connection succeeded
|
# the connection succeeded
|
||||||
else
|
else
|
||||||
result="$cipher $protocols $pubkey $sigalg $trusted $tickethint $ocspstaple $pfs"
|
result="$cipher $protocols $pubkey $sigalg $trusted $tickethint $ocspstaple $pfs $certcns"
|
||||||
verbose "handshake succeeded, server returned ciphersuite '$result'"
|
verbose "handshake succeeded, server returned ciphersuite '$result'"
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
@ -165,7 +196,7 @@ test_cipher_on_target() {
|
|||||||
# Calculate the average handshake time for a specific ciphersuite
|
# Calculate the average handshake time for a specific ciphersuite
|
||||||
bench_cipher() {
|
bench_cipher() {
|
||||||
local ciphersuite="$1"
|
local ciphersuite="$1"
|
||||||
local sslcommand="timeout $TIMEOUT $OPENSSLBIN s_client $SCLIENTARGS -connect $TARGET -cipher $ciphersuite"
|
local sslcommand="$TIMEOUTBIN $TIMEOUT $OPENSSLBIN s_client $SCLIENTARGS -connect $TARGET -cipher $ciphersuite"
|
||||||
local t="$(date +%s%N)"
|
local t="$(date +%s%N)"
|
||||||
verbose "Benchmarking handshake on '$TARGET' with ciphersuite '$ciphersuite'"
|
verbose "Benchmarking handshake on '$TARGET' with ciphersuite '$ciphersuite'"
|
||||||
for i in $(seq 1 $BENCHMARKITER); do
|
for i in $(seq 1 $BENCHMARKITER); do
|
||||||
@ -189,9 +220,9 @@ get_cipher_pref() {
|
|||||||
[ "$OUTPUTFORMAT" == "terminal" ] && [ $DEBUG -lt 1 ] && echo -n '.'
|
[ "$OUTPUTFORMAT" == "terminal" ] && [ $DEBUG -lt 1 ] && echo -n '.'
|
||||||
local ciphersuite="$1"
|
local ciphersuite="$1"
|
||||||
if [ -e $CACERTS ]; then
|
if [ -e $CACERTS ]; then
|
||||||
local sslcommand="timeout $TIMEOUT $OPENSSLBIN s_client -CAfile $CACERTS -status $SCLIENTARGS -connect $TARGET -cipher $ciphersuite"
|
local sslcommand="$TIMEOUTBIN $TIMEOUT $OPENSSLBIN s_client -CAfile $CACERTS -status $SCLIENTARGS -connect $TARGET -cipher $ciphersuite"
|
||||||
else
|
else
|
||||||
local sslcommand="timeout $TIMEOUT $OPENSSLBIN s_client -status $SCLIENTARGS -connect $TARGET -cipher $ciphersuite"
|
local sslcommand="$TIMEOUTBIN $TIMEOUT $OPENSSLBIN s_client -status $SCLIENTARGS -connect $TARGET -cipher $ciphersuite"
|
||||||
fi
|
fi
|
||||||
verbose "Connecting to '$TARGET' with ciphersuite '$ciphersuite'"
|
verbose "Connecting to '$TARGET' with ciphersuite '$ciphersuite'"
|
||||||
test_cipher_on_target "$sslcommand"
|
test_cipher_on_target "$sslcommand"
|
||||||
@ -210,6 +241,7 @@ get_cipher_pref() {
|
|||||||
display_results_in_terminal() {
|
display_results_in_terminal() {
|
||||||
# Display the results
|
# Display the results
|
||||||
ctr=1
|
ctr=1
|
||||||
|
local certcns
|
||||||
local pubkey
|
local pubkey
|
||||||
local sigalg
|
local sigalg
|
||||||
local trusted
|
local trusted
|
||||||
@ -230,6 +262,7 @@ display_results_in_terminal() {
|
|||||||
trusted=$(awk '{print $5}' <<<$cipher)
|
trusted=$(awk '{print $5}' <<<$cipher)
|
||||||
tickethint=$(awk '{print $6}' <<<$cipher)
|
tickethint=$(awk '{print $6}' <<<$cipher)
|
||||||
ocspstaple=$(awk '{print $7}' <<<$cipher)
|
ocspstaple=$(awk '{print $7}' <<<$cipher)
|
||||||
|
certcns=$(awk '{print $9}' <<<$cipher)
|
||||||
else
|
else
|
||||||
if [ "$pubkey" != "$(awk '{print $3}' <<<$cipher)" ]; then
|
if [ "$pubkey" != "$(awk '{print $3}' <<<$cipher)" ]; then
|
||||||
different=True
|
different=True
|
||||||
@ -275,11 +308,28 @@ display_results_in_terminal() {
|
|||||||
fi
|
fi
|
||||||
done|column -t
|
done|column -t
|
||||||
echo
|
echo
|
||||||
|
|
||||||
|
matchhostname=0
|
||||||
|
hostcertcn="Not a match"
|
||||||
|
if [ -z "$certcns" ]; then
|
||||||
|
hostcertcn="CN not found"
|
||||||
|
else
|
||||||
|
IFS=',' read -ra certcnsarray <<<"$certcns"
|
||||||
|
for certcn in "${certcnsarray[@]}"; do
|
||||||
|
if [[ "$certcn" == "$HOST" ]]; then
|
||||||
|
matchhostname=1
|
||||||
|
hostcertcn="$certcn"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
|
||||||
|
fi
|
||||||
if [ $different != "True" ]; then
|
if [ $different != "True" ]; then
|
||||||
if [ "$trusted" == "True" ]; then
|
if [ "$trusted" == "True" ]; then
|
||||||
echo "Certificate: trusted, $pubkey bit, $sigalg signature"
|
echo "Certificate: $hostcertcn, trusted, $pubkey bit, $sigalg signature"
|
||||||
else
|
else
|
||||||
echo "Certificate: UNTRUSTED, $pubkey bit, $sigalg signature"
|
echo "Certificate: $hostcertcn, UNTRUSTED, $pubkey bit, $sigalg signature"
|
||||||
fi
|
fi
|
||||||
echo "TLS ticket lifetime hint: $tickethint"
|
echo "TLS ticket lifetime hint: $tickethint"
|
||||||
fi
|
fi
|
||||||
@ -288,6 +338,13 @@ display_results_in_terminal() {
|
|||||||
else
|
else
|
||||||
echo "OCSP stapling: not supported"
|
echo "OCSP stapling: not supported"
|
||||||
fi
|
fi
|
||||||
|
if [ $matchhostname -eq 0 ]; then
|
||||||
|
echo "WARNING - None of the CNs match the hostname given"
|
||||||
|
fi
|
||||||
|
if [ -n "$certcns" ]; then
|
||||||
|
echo "Here is the list of common names found in the certificate"
|
||||||
|
echo $certcns
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -299,6 +356,7 @@ display_results_in_json() {
|
|||||||
[ $ctr -gt 0 ] && echo -n ','
|
[ $ctr -gt 0 ] && echo -n ','
|
||||||
echo -n "{\"cipher\":\"$(echo $cipher|awk '{print $1}')\","
|
echo -n "{\"cipher\":\"$(echo $cipher|awk '{print $1}')\","
|
||||||
echo -n "\"protocols\":[\"$(echo $cipher|awk '{print $2}'|sed 's/,/","/g')\"],"
|
echo -n "\"protocols\":[\"$(echo $cipher|awk '{print $2}'|sed 's/,/","/g')\"],"
|
||||||
|
echo -n "\"certcns\":[\"$(echo $cipher|awk '{print $9}'|sed 's/,/","/g')\"],"
|
||||||
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')\","
|
||||||
@ -324,6 +382,10 @@ do
|
|||||||
OPENSSLBIN=$2 # You might want to check if you really got FILE
|
OPENSSLBIN=$2 # You might want to check if you really got FILE
|
||||||
shift 2
|
shift 2
|
||||||
;;
|
;;
|
||||||
|
-s | --sni)
|
||||||
|
SNISCAN=1
|
||||||
|
shift
|
||||||
|
;;
|
||||||
-a | --allciphers)
|
-a | --allciphers)
|
||||||
ALLCIPHERS=1
|
ALLCIPHERS=1
|
||||||
shift
|
shift
|
||||||
@ -387,8 +449,11 @@ debug "Port: $PORT"
|
|||||||
TARGET=$HOST:$PORT
|
TARGET=$HOST:$PORT
|
||||||
debug "target: $TARGET"
|
debug "target: $TARGET"
|
||||||
|
|
||||||
|
SNIPARAM=""
|
||||||
SCLIENTARGS=$(sed -e s,${TEMPTARGET},,<<<"${@}")
|
if [ $SNISCAN -gt 0 ]; then
|
||||||
|
SNIPARAM="-servername ${HOST}"
|
||||||
|
fi
|
||||||
|
SCLIENTARGS="$SNIPARAM $(sed -e s,${TEMPTARGET},,<<<"${@}")"
|
||||||
debug "sclientargs: $SCLIENTARGS"
|
debug "sclientargs: $SCLIENTARGS"
|
||||||
|
|
||||||
|
|
||||||
@ -410,7 +475,7 @@ if [ $ALLCIPHERS -gt 0 ]; then
|
|||||||
echo; echo "All accepted ciphersuites"
|
echo; echo "All accepted ciphersuites"
|
||||||
for c in $($OPENSSLBIN ciphers -v ALL:COMPLEMENTOFALL 2>/dev/null |awk '{print $1}'|sort|uniq); do
|
for c in $($OPENSSLBIN ciphers -v ALL:COMPLEMENTOFALL 2>/dev/null |awk '{print $1}'|sort|uniq); do
|
||||||
r="fail"
|
r="fail"
|
||||||
osslcommand="timeout $TIMEOUT $OPENSSLBIN s_client $SCLIENTARGS -connect $TARGET -cipher $c"
|
osslcommand="$TIMEOUTBIN $TIMEOUT $OPENSSLBIN s_client $SCLIENTARGS -connect $TARGET -cipher $c"
|
||||||
test_cipher_on_target "$osslcommand"
|
test_cipher_on_target "$osslcommand"
|
||||||
if [ $? -eq 0 ]; then
|
if [ $? -eq 0 ]; then
|
||||||
r="pass"
|
r="pass"
|
||||||
|
Loading…
Reference in New Issue
Block a user