“心脏滴血漏洞”测评经验分享
“心臟滴血漏洞”測評經驗分享
1 前言
1.1 編寫目的
經驗分析貼,賺C幣買文章;
1.2 讀者對象
本文檔讀者對象為:測評相關工程師、項目管理者、測試工程師、質量管理人員、文檔工程師等技術人員。
| 測評工程師 | 建議閱讀全部內容。 |
| 項目管理者 | 建議閱讀軟件介紹概要性文檔。 |
| 質量管理人員 | 建議閱讀介紹等概要性文檔。 |
| 文檔工程師 | 建議閱讀介紹概要性文檔。 |
1.3 名詞術語
| 緩沖區過讀 | 緩沖區過讀是一類程序錯誤,即程序從緩沖器讀出數據時超出了邊界,而讀取了(或試圖讀取)相鄰的內存。 |
| OpenSSL | OpenSSL是一個開放源代碼的軟件庫包,應用程序可以使用這個包來進行安全通信,避免竊聽,同時確認另一端連接者的身份。這個包廣泛被應用在互聯網的網頁服務器上。 |
| 完全正向保密 | 完全正向保密(perfect forward secrecy)是信息安全中提出的觀點。要求一個密鑰只能訪問由它所保護的數據;用來產生密鑰的元素一次一換,不能再產生其他的密鑰;一個密鑰被破解,并不影響其他密鑰的安全性。設計旨在長期使用密鑰不能確保起安全性的情況下而不影響過去會話的保密性。 |
1.4 參考文檔
| 1 | Rix Tox(知乎) | https://www.zhihu.com/question/23328658/answer/24236735 | 無 |
2 測評前的準備
2.1 心臟滴血漏洞是什么?
? ?? ? Heartbleed漏洞,也叫“心臟滴血漏洞”。是OpenSSL加密軟件庫中的一個嚴重漏洞。這個漏洞允許竊取正常情況下使用SSL/TLS加密保護的信息;
? ?? ?自2011年12月31日,漏洞就已經存在,而且隨著OpenSSL版本1.0.1于2012年3月14日釋出,有缺陷的代碼被互聯網廣泛使用;Heartbleed漏洞允許互聯網上的任何人不受限制的讀取受OpenSSL漏洞保護系統的內存。攻擊者可根據漏洞竊聽信息,直接從服務和用戶那里竊取潛在的敏感數據,甚至包括服務器的專用主密鑰;
? ?? ?如果存在此漏洞;攻擊者可以通過被動中間人攻擊,獲取此時服務器內存中存儲的信息(如果服務器和客戶端未使用完全正向保密,或使用了完全正向保密時攻擊方發動“主動中間人攻擊”)。攻擊者無法控制服務器返回的數據,因為服務器會使用一個隨機內存塊(最大64KB)作為響應;而且攻擊者可以不斷發送攻擊請求報文,獲取服務器內存中的數據。
? ?? ?安全公司Codenomicon和Google工程師Neel Mehta最早于2014年4月8日發現(公布)了 OpenSSL的Heartbleed漏洞;安全公司Codenomicon為這個漏洞制作了一個符合漏洞形象的logo;Codenomicon公司的工程師“Ossi Herrala”為漏洞名起了很炫的名字:“Heartbleed”;心臟滴血的名稱由此而來。
2.2 漏洞范圍
? ?? ?Heartbleed于2011年12月被引入到OpenSSL中,自OpenSSL于2012年3月14日發布1.0.1以來就一直存在。2014年4月7日發布的OpenSSL 1.0.1g修復了這個漏洞。.
| 存在漏洞的版本 | OpenSSL1.0.1、1.01a、1.01b、1.01c、1.01d、1.01e、1.01f、Beta 1 of OpenSSL1.02等版本 |
| 不存在漏洞的版本 | OpenSSL1.0.1g、OpenSLL1.0.0、OpenSSL 0.9.8、OpenSSL 1.0.2-beta2、和以上SLL高版本 |
? ?? ?漏洞詳細說明見:https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-0160
? ?? ?自2014年漏洞發布起即全球%30的網站存在被攻擊的風險,漏洞影響的范圍到底有多大? 根據以下當年發布的信息可以說明情況;
? ?? ?節選來自Heartbleed的官方說明:OpenSSL在Web容器如Apache/Nginx中使用,這兩款中間件的全球份額超過66%。一些大型的互聯網公司常使用 OpenSSL,而這曾經被認為是最安全的數據傳輸手段之一;
? ?? ?眾多網絡路由器廠商包括 Cisco Systems 與 Juniper Networks等,在漏洞公布當天紛紛發布了緊急公告,列出一系列受此漏洞影響的路由器產品。雖說這些產品由于使用舊版SSL,廠商也表示會盡快更新補洞,據悉,有的黑客在漏洞發布一年前就已經在利用這個漏洞了,獲取到了不少大網站的敏感信息;
? ?? ?國內知名企業如淘寶、阿里、360、京東(滾動資訊)、微信、支付寶等公司的技術團隊也在漏洞發布當天徹夜奮戰,和黑客們開展起了一場“你盜我堵”的賽跑,在黑客竊取更多用戶數據前趕緊予以修復…
? ?? ?下面圖片反應了2014年在發布漏洞后的緊急情況:
2.3 漏洞描述
? ?? ?Heartbleed漏洞,這項嚴重缺陷(CVE-2014-0160)的產生是由于未能在memcpy()調用受害用戶輸入內容作為長度參數之前正確進行邊界檢查。攻擊者可以追蹤OpenSSL所分配的64KB緩存、將超出必要范圍的字節信息復制到緩存當中再返回緩存內容,這樣一來受害者的內存內容就會以每次(每次SSL心跳報文請求)64KB的速度進行泄露;原理如下圖所示:
2.4 漏洞原理
2.4.1 心跳檢測報文(Heartbeat)
? ?? ?要對心臟滴血漏洞進行更好的理解,首先需要知道心跳檢測報文的作用和運行原理,這里做簡要解釋;
(A)心跳檢測報文的作用
? ?? ?TLS心跳擴展報文為TLS/DTLS提供了一種允許在不重新進行商議和發送路徑MTU探索包(PMTU)的情況下而使用保持持續通信功能的新協議。
所謂心跳檢測,就是建立一個 Client Hello 問詢來檢測對方服務器是不是正常在線 ,服務器發回 Server hello,表明正常保持SSL通訊。就像我們打電話時會問對方“喂聽得到嗎?”一樣;
? ?? ?每次問詢都會附加一個問詢的字符長度“pad length”,如果這個“pad length” 大于實際的長度,應答方仍是會返回相同字符長度的字符信息。
(B)TLS/DTLS心跳檢測報文的結構
? ?? ?TLS數據包格式如下:
| ContentType | 1byte | 心跳包類型,IANA組織把type編號定義為24(0x18) |
| ProtocolVersion | 2bytes | TLS的版本號,目前主要包括含有心跳擴展的TLS版本:TLSv1.0,TLSv1.1,TLSv1.2 |
| length | 2bytes | HeartbeatMessage的長度 |
| HeartbeatMessageType | 1byte | Heartbeat類型 01表示heartbeat_request 02表示heartbeat_response |
| payload_length | 2bytes | payload長度 |
| payload | payload_length個bytes | payload的具體內容 |
| padding | >=16bytes | padding填充,最少為16個字節 |
? ?? ?DTLS數據包格式如下:
| pe | 1byte | 心跳包類型,IANA組織把type編號定義為24(0x18) |
| ProtocolVersion | 2bytes | DTLS的版本號,DTLS1.0基于TLS1.1,DTLS1.2基于TLS1.2 |
| epoch | 2bytes | 為一個計數器,每一個加密狀態改變時加一。主要用來區分在一個多次重新協商的情況,多個記錄包文可能會具有相同的序列號,因此再用這個域來區分,接收者可以用來區分不同的包。epoch初始值為0,每發送一個changeCipherSpec消息后加一 |
| sequence_number | 6bytes | 記錄層的序列號,在每一個ChangeCipherSpec消息發送之后,sequence_number都設置為0 |
| length | 2bytes | HeartbeatMessage的長度 |
| HeartbeatMessageType | 1byte | Heartbeat類型 01表示heartbeat_request 02表示heartbeat_response |
| payload_length | 2bytes | payload長度 |
| payload | payload_length個bytes | payload的具體內容 |
| padding | >=16bytes | padding填充,最少為16個字節 |
(C)TLS/DTLS心跳檢測報文抓包示范
? ?? ?心跳檢測報文包括A、請求包(heartbeat Request)和B、響應包(heartbeat Response);本文以常見TLS數據包為例,通過wireshark進行抓包獲取信息如下:
A、TLS請求包抓包示例如下:
B、TLS響應包抓包示例如下:
? ?? ?通過對比心跳檢測請求報文和響應報文不難看出,響應報文和請求報文使用相同的報文格式;如果仔細觀察請求報文,可以發現請求報文請求的報文長度是16384,但實際的載荷(Payload)值為0;但應答方回復請求方的實際載荷(Payload)為16381(約64KB);這里,就是心臟發生滴血的地方;即可以發現攻擊方通過制造畸形心跳檢測請求報文進行了攻擊;
? ?? ?如果打開應答報文Payload字段,可以看到因漏洞產生內存溢出的數據;溢出的數據是隨機的,但是攻擊方可以通過多次進行攻擊,從而獲取更多應答方內存中的數據,直到獲取有價值的數據;而且64KB是可以泄露出足夠多的信息的;如下圖攻擊方通過偽造報文已經獲取了關鍵的用戶賬戶和口令信息:
? ?? ?這里還想說一些題外話,此類漏洞主要是因為攻擊方制造了畸形報文進行了攻擊,目前可以抵御的手段可以通過IPS、WAF等安全防護規則庫進行攔截;但根本上最好的修復方法還是更新SSL/TLS版本;后續的SSL/TLS版本中對協議代碼進行了優化(對輸入內容作為長度參數之前正確的進行了邊界檢查)。
2.4.2 代碼原理示例
? ?? ?漏洞出現在SSL服務ssl/d1_both.c中,對用戶傳入的payload長度沒有檢查就進行內存拷貝;下面是代碼示意:
漏洞出現在SSL服務ssl/d1_both.c中,對用戶傳入的payload長度沒有檢查就進行內存拷貝;下面是代碼示意: 1)基本結構 ------------------------------------------------------------------------- int dtls1_process_heartbeat(SSL *s){ unsigned char *p = &s->s3->rrec.data[0], *pl;unsigned short hbtype;unsigned int payload;unsigned int padding = 16; /* Use minimum padding */ } ------------------------------------------------------------------------- 2)p指向一條SSLv3的記錄,結構如下: ------------------------------------------------------------------------- typedef struct ssl3_record_st{int type; /* type of record */unsigned int length; /* How many bytes available */unsigned int off; /* read/write offset into 'buf' */unsigned char *data; /* pointer to the record data */unsigned char *input; /* where the decode bytes are */unsigned char *comp; /* only used with decompression - malloc()ed */unsigned long epoch; /* epoch number, needed by DTLS1 */unsigned char seq_num[8]; /* sequence number, needed by DTLS1 */} SSL3_RECORD; ------------------------------------------------------------------------- 3)回到上面的程序,接下來對指針進行一些操作: ------------------------------------------------------------------------- /* Read type and payload length first */ hbtype = *p++; n2s(p, payload); pl = p; -------------------------------------------------------------------------4)這里先讀取個type,然后n2s把下一個length的兩個字節放到payload里面,作為后面內存拷貝的長度; ------------------------------------------------------------------------- unsigned char *buffer, *bp; int r;/* Allocate memory for the response, size is 1 byte* message type, plus 2 bytes payload length, plus* payload, plus padding*/buffer = OPENSSL_malloc(1 + 2 + payload + padding); bp = buffer;/* ... *//* Enter response type, length and copy payload */ *bp++ = TLS1_HB_RESPONSE; s2n(payload, bp); memcpy(bp, pl, payload); ------------------------------------------------------------------------- 注意這個payload長度是用戶請求的,而在分配的時候完全沒有對于實際的SSL記錄長度進行審查,bp會直接返回給用戶,所以攻擊者可以dump出任意長度(最大為65535(payload)+1+2+16(padding)=64k)的數據,而pl也是用戶傳入的,只要把pl設置的很小,dump出來的數據就會包含更多別的敏感數據。具體的利用方法見exploit demo,就不詳細分析了。作者:Rix Tox 鏈接:https://www.zhihu.com/question/23328658/answer/24236735 來源:知乎3 測評實施要點
? ?? ?通過上文對心臟滴血漏洞的理解,測評過程中無非是存在四個需要解決的問題;一是怎么發現,二是怎么測試,三是怎么寫;四是怎么判定風險。本文不涉及滲透類測試,不提供漏洞POC測試工具下載。
3.1 發現漏洞的方法
(A)通過協議版本判斷
? ?? ?如本文2.2章節漏洞范圍中【=存在心臟滴血漏洞的SSL/TLS相關版本】所示,當前存在心在滴血漏洞的版本有OpenSSL1.0.1、1.01a、1.01b、1.01c、1.01d、1.01e、1.01f、Beta 1 of OpenSSL1.02等版本;如果當前所使用SSL技術包括以上版本,則可能存在漏洞。
3.2 測試漏洞的方法
(A)通過Wireshark抓包測試(包分析)
? ?? ?1)異常的SSL心跳檢測請求報文會在Wireshark軟件中自動標識出來,這里不得不說測評工具的重要性;如下圖,Wireshark在發現異常報文后,將會用紅色覆蓋異常字段;再通過人工判斷可以發現當前載荷和請求載荷內容明顯存在問題;
? ?? ?2)找到應答報文,可以發現內存溢出的信息,其中包括了用戶名和口令;
(B)通過Wireshark抓包測試(TCP追蹤)
? ?? ?根據心跳檢測報文原理我們知道心跳檢測報文是用于保證單次會話的連通性;因此我們可以根據TCP流追蹤取,可以獲取到未通過TLS加密的部分(其實是內存溢出,和加密無關);如下圖:
3.3 描述漏洞的方法
? ?? ?知道了怎么發現、測試的方法,描述方面即只要包括關鍵截圖和發現的過程內容即可;重點是描述出當前使用的SSL/TLS協議版本;指出存在心臟滴血漏洞,然后將測試過程截圖保存再結果記錄表后面,相關描述見“結果記錄表“編寫規范,這里不多做概述。
3.4 判定風險的方法
? ?? ?依據公開的“信息系統密碼應用高風險判定指引”;此類漏洞風險被歸類到密碼產品和密碼服務,且屬于高風險項;依據截圖如下:
? ?? ?判定方面,因實際采用了密碼技術,因此不能給不符合;在本文中,密碼套件為TLS_EDCDHE_RSA_WITH_AES_256_CBC_SHA(0xc014);不考慮密鑰管理方面,這里應該給部分符合;
? ?? ?即:部分符合,存在高風險(高風險判定指引第5.3章,hearbleed高風險漏洞)。
4 總結
? ?? ?以上是本次相關心臟滴血漏洞的分享內容,通過對漏洞的歷史、重要性、原理、測試方法等進行了回顧,有助于我們對漏洞進行更好的理解,并根據漏洞情況編寫結果記錄;本文沒有關于滲透類POC相關測試的內容,理論篇借鑒了CDSN和知乎上各類文章,比較重要的文章已標注內容來源;個人理解部分歡迎指出問題;
? ?? ?需要說明的是,雖然是2014年曝光的漏洞,但是目前依然可能有不少使用低版本的TLS/SSL協議的情況,因此此類漏洞,需要及時發現。
總結
以上是生活随笔為你收集整理的“心脏滴血漏洞”测评经验分享的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Quick BI简要使用
- 下一篇: Mathtype常用快捷键