Heartbleed: OpenSSL密碼與加密密鑰泄露漏洞剖析
此次名為Heartbleed的OpenSSL漏洞引發(fā)了極其惡劣的影響,而為此暫時(shí)切斷互聯(lián)網(wǎng)連接肯定也不算什么理想的解決方案。僅僅由于廣泛使用的加密機(jī)制中存在一丁點(diǎn)微小缺陷,如今任何家伙都能輕松潛入存在漏洞的系統(tǒng)——包括銀行HTTPS服務(wù)器以及個(gè)人VPN——并瘋狂竊取密碼、登陸cookie、個(gè)人加密密鑰等等。
現(xiàn)在已經(jīng)是2014年了,安全保障工作為何仍然如此不堪?
只需一份利用Metasploit引擎的簡(jiǎn)單腳本外加短短幾秒鐘,惡意人士即可從依賴于OpenSSL 1.0.1到1.0.1f版本進(jìn)行TLS加密的系統(tǒng)內(nèi)存中提取到敏感數(shù)據(jù)。根據(jù)我們掌握的情況,這一漏洞影響到的網(wǎng)站約為五十萬(wàn)個(gè)、占總體受信網(wǎng)站中的17.5%,此外任何使用上述OpenSSL版本的客戶端軟件、郵件服務(wù)器、聊天服務(wù)等也都在受影響范圍之內(nèi)。
本周一開(kāi)始已經(jīng)有不少熱門網(wǎng)絡(luò)服務(wù)陸續(xù)針對(duì)這一漏洞發(fā)布修復(fù)補(bǔ)丁;大家可以利用相關(guān)工具檢查自己的系統(tǒng)是否已經(jīng)中招(當(dāng)然,風(fēng)險(xiǎn)要由各位自己承擔(dān)),同時(shí)也別忘了為自己已經(jīng)受到感染的系統(tǒng)安裝OpenSSL修復(fù)補(bǔ)丁。除此之外,我們還需要更改密碼、轉(zhuǎn)儲(chǔ)會(huì)話cookie并對(duì)數(shù)據(jù)風(fēng)險(xiǎn)加以評(píng)估。
如果大家還不了解Heartbleed是怎么回事,這里提供概括描述:
這項(xiàng)嚴(yán)重缺陷(CVE-2014-0160)的產(chǎn)生是由于未能在memcpy()調(diào)用受害用戶輸入內(nèi)容作為長(zhǎng)度參數(shù)之前正確進(jìn)行邊界檢查。攻擊者可以追蹤OpenSSL所分配的64KB緩存、將超出必要范圍的字節(jié)信息復(fù)制到緩存當(dāng)中再返回緩存內(nèi)容,這樣一來(lái)受害者的內(nèi)存內(nèi)容就會(huì)以每次64KB的速度進(jìn)行泄露。大家可以點(diǎn)擊此處獲取修復(fù)補(bǔ)丁,需要強(qiáng)調(diào)的是此次問(wèn)題遠(yuǎn)比蘋果前一陣子曝出的安全問(wèn)題嚴(yán)重得多。
問(wèn)題源自TLS Heartbeat擴(kuò)展
這一漏洞藏身于OpenSSL的TLS Heartbeat擴(kuò)展當(dāng)中:這是一項(xiàng)持續(xù)作用型功能,其中一個(gè)連接端會(huì)向另一端發(fā)送任意數(shù)據(jù)的有效負(fù)載,對(duì)方則發(fā)回對(duì)應(yīng)數(shù)據(jù)的精確副本以確保傳輸過(guò)程一切正常。根據(jù)官方提供的標(biāo)準(zhǔn)說(shuō)明,Heartbeat信息在C語(yǔ)言中表現(xiàn)為以下形式:
這條HeartbeatMessage通過(guò)SSL3_RECORD結(jié)構(gòu)——一種SSL/TLS通信基礎(chǔ)構(gòu)建塊——進(jìn)行傳輸。SSL3_RECORD中的關(guān)鍵性字段如下所示,其中l(wèi)ength代表接收到的HeartbeatMessage內(nèi)容為多少字節(jié)、data則為指向該HeartbeatMessage的指針。
更明確地進(jìn)行解釋,SSL3記錄中的data指向接收到的HeartbeatMessage的起始位置,而length代表接收到的HeartbeatMessage的字節(jié)數(shù)量。與此同時(shí),HeartbeatMessage中的payload length代表被發(fā)回的隨意有效負(fù)載的字節(jié)數(shù)量。
發(fā)出HeartbeatMessage的一方對(duì)payload length擁有控制權(quán),不過(guò)正如我們所看到,SSL3_RECORD中的length字段并沒(méi)有經(jīng)過(guò)驗(yàn)證、而這一狀況就成了攻擊者實(shí)現(xiàn)內(nèi)存溢出絕佳機(jī)會(huì)。
以下圖表顯示了相關(guān)攻擊活動(dòng)的工作原理:
請(qǐng)注意:其中并不包含填充字節(jié)
在上面的例子中,攻擊者在發(fā)出的HeartbeatMessage當(dāng)中包含了僅為1字節(jié)的有效負(fù)載,這一情況也被反映在了SSL3的length記錄當(dāng)中;不過(guò)payload length字段要求有效負(fù)載長(zhǎng)度應(yīng)該為65535字節(jié)。受害者忽略了SSL3記錄,轉(zhuǎn)而從內(nèi)存接收到的HeartbeatMessage起始處開(kāi)始讀取65535字節(jié)的數(shù)據(jù)并將其復(fù)制到緩存當(dāng)中,最終以合適的長(zhǎng)度發(fā)送回攻擊者處。由于包含大量額外字節(jié),上圖中紅色單元格所示即為可能導(dǎo)致信息泄露的數(shù)據(jù)部分。
從代碼角度分析
以下代碼為OpenSSL對(duì)HeartbeatMessage輸入內(nèi)容的處理方式,其中p為指向該信息起始處的指針:
這樣一來(lái),信息類型就被體現(xiàn)在hbtype變量當(dāng)中,該指針由1字節(jié)開(kāi)始遞增,而n2s()宏將長(zhǎng)度為16-bit的Heartbeat有效負(fù)載寫入到payload變量中并將該指針增加到2字節(jié)。接下來(lái),pl又成為指向這部分有效負(fù)載內(nèi)容的指針。
舉例來(lái)說(shuō),一條Heartbeat信息中的payload length為65535字節(jié),即:一條接收到的Heartbeat中最多可能包含64KB有效負(fù)載。代碼必須將輸入的HeartbeatMessage以副本形式發(fā)送回去,從而保證緩存區(qū)擁有足夠的空間來(lái)保存64KB有效負(fù)載、1字節(jié)信息類型、2字節(jié)有效負(fù)載長(zhǎng)度外加部分填充字節(jié),具體結(jié)構(gòu)如前所述。
它會(huì)利用以下代碼創(chuàng)建HeartbeatMessage回復(fù)結(jié)構(gòu),其中bp為指向HeartbeatMessage回復(fù)起始位置的指針:
因此這部分代碼會(huì)將響應(yīng)類型寫入到緩存起始位置、遞增緩存指針、利用s2n()宏向內(nèi)存中寫入16-bit payload長(zhǎng)度并以2字節(jié)為單位遞增緩存指針,而后將payload的字節(jié)數(shù)量從接收到的有效負(fù)載中復(fù)制到用于回復(fù)的有效負(fù)載發(fā)送內(nèi)容中。
請(qǐng)注意,payload由攻擊者全面控制,而且64KB也足以容納大量信息。假如由攻擊者發(fā)送的HeartbeatMessage只擁有1字節(jié)有效負(fù)載,而且其payload length又與實(shí)際情況不符,那么以上代碼中的memcpy()就會(huì)在接收到的HeartbeatMessage之外從起始處讀取受害者的內(nèi)存進(jìn)程。
而這部分內(nèi)存很可能包含其它意義重大的信息,例如密碼內(nèi)容或者來(lái)自其它客戶端的加密信息等。
事實(shí)上,盡管我們了解到雅虎已經(jīng)對(duì)其系統(tǒng)進(jìn)行了修復(fù),但該公司仍然發(fā)布了如下建議:
請(qǐng)不要登陸雅虎網(wǎng)站。目前OpenSSL漏洞Heartbleed允許攻擊者提取用戶名以及簡(jiǎn)單密碼信息!
— Mark Loman (@markloman),2014年4月8號(hào)
修復(fù)手段
OpenSSL 1.0.1g中的補(bǔ)丁從本質(zhì)上講就是一項(xiàng)邊界檢查,旨在利用SSL3結(jié)構(gòu)(s3->rrec)中的正確長(zhǎng)度記錄描述輸入的HeartbeatMessage。
OpenSSL是在2011年12月31號(hào)星期六午夜期間耗時(shí)61分鐘完成TLS Heartbeat項(xiàng)目源代碼提交工作的。如今我們所承受的各種威脅可謂一場(chǎng)姍姍來(lái)遲的安全風(fēng)暴。