資安事件與漏洞
Heartbleed(CVE-2014-0160)——加密通訊的根基洩漏了記憶體的事件
2014 年,支撐全球 HTTPS 通訊的 OpenSSL 中發現了會把伺服器記憶體內容洩漏到外部的漏洞 Heartbleed。連私鑰、工作階段資訊都可能被竊取的嚴重性、為何會發生的原理圖解、時間軸,以及『一旦外洩就按全部外洩處理』『更換金鑰與憑證』這一至今未變的教訓,本文用圖與表為你講解。
回顧過去的重大事件,只聚焦於對當下你的維運真正有用的教訓。我們不重現攻擊,而是從防禦的視角來解讀。
發生了什麼——「回傳的比請求的多」
TLS(HTTPS 的加密)中有一種用於維持連線的「存活確認(heartbeat)」互動。用戶端傳送一小段資料和一個「把這個回傳給我」的長度,伺服器照樣回傳——本來這只是個如此簡單的機制。
OpenSSL 的實作沒有檢核這個申報的長度。明明實際只傳送了幾個位元組,卻申報「回傳 64KB」,伺服器就會超出收到的資料量,把相鄰的記憶體也一併讀取並回傳。如果那裡恰好存著私鑰或工作階段,它們也會一起洩漏。
正常:傳送的長度=回傳的長度
「回傳 "bird"(4 個字元)・長度 4」→ 伺服器「bird」
Heartbleed:短傳送+大申報長度
「回傳 "bird"(4 個字元)・長度 64KB」→ 伺服器「bird+相鄰的記憶體 64KB(可能包含私鑰、工作階段等)」
攻擊方不需要任何特殊權限。透過反覆多次操作,就能一點點蒐集到記憶體的碎片。根基中的根基——TLS 函式庫裡的一個小 bug,動搖了全世界通訊的信任。
“不留痕跡的洩漏”之可怕
Heartbleed 不易在常規的存取日誌中留下痕跡,事後很難斷定「是否洩漏了」「洩漏了什麼」。一旦難以判斷,按最壞情況行動才是正解。
時間軸
2014-04-07
漏洞被公開,修復版 OpenSSL 同時發布。公開後不久
全球伺服器一齊著手修補。影響範圍之廣引發一片譁然。此後
許多服務按「私鑰已外洩」的前提撤銷並重新簽發憑證,並呼籲使用者更改密碼。
為什麼「只修補」並不算結束
既然私鑰有可能已經洩漏,那麼即便修補了,過去外洩的金鑰仍然有效。所以應對要分兩步走——堵住漏洞(修補)+按已外洩的前提更換資產(金鑰、憑證、機密)。
不充分的應對
- 更新 OpenSSL 後就認為「已經修好了」
- 只更換確認被利用的那一個機密
- 憑證繼續照常使用
正確的應對
- 在更新之外,還要撤銷並重新簽發憑證(重新產生私鑰)
- 徹底更換伺服器持有的機密、金鑰、密碼
- 督促使用者更改密碼
對當下有用的教訓
按『一旦外洩就是全部外洩』處理
不是只換已確認的那一個,而是徹底更換伺服器持有的機密、金鑰、密碼。面對不留痕跡的洩漏,按最壞情況行動才安全。
撤銷並重新簽發憑證
既然私鑰有可能已經洩漏,憑證也要重新產生。只要不輪替金鑰,過去的洩漏就會一直存活下去。
把“根基軟體”也納入監控對象
不只是應用程式,像 OpenSSL 這樣的根基軟體的 CVE 也要用機器監控來追蹤。越是根基,影響範圍越廣。
理解記憶體安全的價值
「讀取的比請求的多」這類 bug,可以透過記憶體安全的設計與語言從結構上減少。把它納入選擇根基軟體的考量。
接下來閱讀
- 術語:什麼是 CVE
- 事故:.env 公開導致全部機密外洩的故事
- 入門:如何守護機密·超入門
FAQ
QHeartbleed 可能洩漏了什麼?
伺服器的記憶體內容。運氣不好時,可能包含 TLS 私鑰、工作階段內容、登入資訊等。而且這種洩漏不易留下痕跡,事後很難確定『到底洩漏了多少』,這正是棘手之處。
Q為什麼會發生『回傳的比請求的多』?
在維持連線的存活確認(heartbeat)中,伺服器沒有檢核對方申報的『希望回傳的長度』就直接信任了。明明實際只傳送了很短的資料,卻申報『回傳 64KB』,伺服器就會把相鄰的記憶體一併讀取並回傳。信任了輸入(長度)正是漏洞所在。
Q應對中最重要的是什麼?
修補之後要『按已外洩處理』。具體而言,就是撤銷並重新簽發 TLS 憑證,以及徹底更換伺服器持有的機密與密碼。僅僅修復應用程式是不夠的。