OpenSSL嚴重安全漏洞CCS
繼之前爆出的“心臟出血”漏洞後,openSSL再被爆出另一個嚴重漏洞,最初在開源中國看到文章時把CCS看成了CSS,囧~~
“OpenSSL 的 ChangeCipherSpec 處理再報嚴重安全漏洞,該漏洞使得攻擊者可以攔截惡意中間節點加密和解密資料,同時迫使使用弱金鑰的SSL客戶端暴露在惡意節點。”
借用文章裡的CCS注入的圖:
下面翻譯漏洞發現者的部落格:“我是如何發現CCS注入攻擊的”.
原文地址:http://ccsinjection.lepidum.co.jp/blog/2014-06-05/CCS-Injection-en/index.html
什麼是CCS注入漏洞
在客戶端和服務端握手階段,OpenSSL協議不合時宜地接受密碼更換說明(ChangeCipherSpec :CCS),而產生了該漏洞。而且,從第一個版本的OpenSSL起,這個漏洞就一直存在。
如圖,在握手階段需要兩次傳送ChangeCipherSpec訊息,OpenSSL也確實是按照正確的時間傳送CCS,然而,CCS訊息卻可以在其他時間裡被接收。攻擊者就可以利用這一行為解密或者修改傳輸通道里的資料。
發現漏洞有多難
造成CCS漏洞16年沒有被發現的原因是OpenSSL實現缺少全面的程式碼審查(code reviews)。如果審查者有一定的TLS和SSL開發經驗,那麼他們就應該能自己發現這個問題。
模糊測試也許很有效,但歷史經驗表明,擁有TLS/SSL開發經驗對發現OpenSSL安全問題尤為重要:
CVE-2004-0079是Codenomicon發現CCS漏洞,也是第一個CCS漏洞。 之後
這個漏洞是因為在DTLS握手階段太早地接收CCS訊息,造成了分段錯誤。針對CCS時序驗證也並沒有很好滴被解決。
DTLS fragment retransmission bug
該補丁增加了對不可預測報文衝排序的驗證,解決了DTLS握手中的CCS時序問題。進一步分析該補丁可以發現,一個非計算的主金鑰被用來加密,這個值被告知是從未被初始化的記憶體中讀取的,不能使用隨機值。然而事實是:這個值是一串空位元序列,如果這個問題被及早發現,這個CCS攻擊的可能性將大大降低。
正確實現CCS有多難?
答案是:非常簡單! 只需要保證CCS的傳送和接收順序都按照上圖中的協議流程進行。然而這裡包含了一個意外:CCS訊息的序列標識和其他握手訊息的序列標識不是同一種類型。RFC的解釋如下:
Note: To help avoid pipeline stalls, ChangeCipherSpec is
an independent SSL Protocol content type, and is not
actually an SSL handshake message.
draft-ietf-tls-ssl-version3-00 §5.5我認為,這個決定就是導致CCS脆弱性的根源。根據RFC給出的解釋,CCS使用獨立的序列標識(也就是說CCS不算是真正的SSL握手訊息)是為了避免“流水線停頓”(pipeline stall)。這就使得TLS/SSL的握手階段需要非常複雜的同步機制:首先,OpenSSL協議需要等待握手過程進行到合適的階段;其次,協議需要去檢查握手階段在結束之前是否接受到CCS訊息。
詳細地,當接收到CCS訊息時,需要檢驗以下三個情況:(*)
- 握手過程是否進行到合適階段,例如是否是在握手結束之前收到
- 握手過程沒有其他片段
- 下一個訊息是否完成
更需要小心的是你還得檢查下面兩個情況(詳見Alert attack.):
- 沒有警告片段
- 沒有心跳片段
RFC估計是想表達出下面兩個顧慮:
- 避免CCS被夾雜在其他握手片段裡傳輸。
- 為了避免流水線停頓,伺服器和客戶端都需要傳送CCS訊息。
我是如何發現這個漏洞的
“心臟出血”漏洞暴露後,大家都在討論和研究如何避免類似這種的bug,單元測試、程式碼分析、fork and rewrite cleanly, improve API, not to reinvent malloc, 結合C以外的其他語言進行測試,這些技術都被用來測試OpenSSL的安全性。
ATS就是其中一種比較受歡迎的測試語言。我思考過,用Coq(形式化驗證管理系統) 來驗證ATS寫的TLS/SSL。證明協議的安全性是一個巨大的工作,雖然它不會有助於實現安全,我一直在嘗試一些方法能夠清楚明瞭地展示協議實現的正確性。
我的目標是:
- 直譯器(parsers)和輸出機(printers)能完美耦合
- 輸出機能被正確實現
- 狀態機的行為用謂詞表示
考慮*標識的三個情況,我開始關注CCS上的狀態轉換,CCS狀態轉換是狀態機裡最複雜的部分。
隨後,檢查當前實現是否正確考慮到這些情況。我發現除了OpenSSL,大多數的實現多多少少都考慮到了。OpenSSL沒有考慮這些情況,OpenSSL也就有CCS漏洞!
第一次翻譯,有什麼不當之處,希望指出。