天天看點

OpenSSL再曝CCS注入漏洞-心傷未愈又成篩子

太戲劇了,昨晚看了佳片有約,還不錯,2012版的《完美回憶》,像我這種人依然選擇用電視或者去影院看電影,在沒有中間插播廣告的時候,體驗憋尿得過程 中,總是能突然有很多的想法,這是用電腦或者手機看電影所體會不到的。看完以後已經12點半了,突然想再看一遍《黑客帝國》,這下不用電腦不行了,因為電 視上沒得播...結果正在緩沖的時候,突然看到了旁邊的小公告:“OpenSSL再爆嚴重安全漏洞--CCS注入”,完了,電影看不成了,不是說不想看 了,突然感覺自己比神還無恥,怎麼人家曝出漏洞會這麼高興啊,關掉已經緩沖完畢的電影,就想看一下OpenSSL的笑話,同時心裡還極度扭曲地想,我不最 近在搞基于OpenSSL的一個修改麼,向OpenSSL這種代碼,就我這種垃圾coder配得上它,因為我的垃圾代碼和它很般配...

       我們知道,OpenSSL協定分了兩個層次,一個是記錄協定層,一個是資料協定層,後者包含了握手協定,告警協定,CCS協定等,注意這個“等”字,搞知 道國密标準的應該知道這個等字的含義,不知道國密标準的人奉勸永遠都不要知道,這次的CCS漏洞本質上就和這個“等”字有關。言歸正傳,SSL/TLS的 安全通道通過握手協定建立,安全通道上通行的資料顯然是加密的,而在握手過程中,在密鑰等安全參數沒有協商完成之前,資料都是明文的,那麼在握手狀态機中 就肯定有那麼一個點,在該點之前資料是明文的,而在該點之後資料是加密的,這個點就是接收到ChangeCipherSpec消息,問題是,這個消息在握 手狀态機中交換,但是卻不在握手協定中定義,它被定義為一個單獨的協定,不屬于握手協定。這樣做的理由,按照漏洞發現者Masashi Kikuchi在RFC挖掘出的理由那就是:

Note:          To help avoid pipeline stalls, ChangeCipherSpec is

                 an independent SSL Protocol content type, and is not

                 actually an SSL handshake message.

在之前的漏洞影響的版本中,并沒有确認master_key_length不為0,這就意味着即便master key還沒有準備好,也是可以發送CCS的,而這樣的話,所謂的密鑰也沒有秘密可言了。CCS的發送時間并沒有強制要求,但是要求master keys必須準備好!以下是一個基于中間人攻擊的漏洞利用場景,中間人在作為server的時候,在ServerHelloDone完成後即發送一個 CCS,注意此時還沒有生成master keys,是以使用一個空值代替,由于OpenSSL在收到CCS的時候并沒有檢查自己的握手狀态機處于哪一步驟,是以會無條件接收,此時它也沒有 master key,後面的事情就是使用不是密鑰的密鑰對資料進行加密,注意,由于OpenSSL的實作原因,隻要已經經過了key的計算,在一個session中以 後就不會再次計算,是以下面的代碼(同樣處于ssl3_do_change_cipher_spec中)事實上助長了漏洞:

    關于SSL/TLS規範中将CCS設計成獨立的一個資料協定,我在《TCP/IP協定族》這本經典教材中找到了更真切的理由,那就是它将發送方和接收方分割成了兩個狀态,按照分權原則,這個事不能在握手協定本身完成。

    漏洞發現者Masashi Kikuchi所述,隻要保證幾點即可,非常簡單:

IMHO, this sentence is the very cause of the vulnerability. According to it, the reason that CCS is assigned an independent record type is to avoid a stall. This is the point where the most complex synchronization is required in TLS/SSL handshake. First, you need to wait until the handshake proceeds to the proper phase. Then, you need to check whether the handshake receives CCS before Finish.

More precisely, when accepting CCS, you must verify the following three conditions (*):

    the handshake proceeds to the proper phase, i.e., just before to receive Finished,

    no fragments from the handshake remains,

    and, the next message is Finished.

Being more careful, you should also check

    no Alert fragment remains (they can be rejected in the first place),

    and, no Heartbeat fragment remains

事實很簡單,保證CCS發送的時候,master keys真的已經準備好了,這實際上就是CCS本身的意思,如果我能跟我的三歲的小小講清楚這個,她肯定會說她的口頭禅:難道不是嗎?

       一個獨立的CCS協定,獨立于握手協定的CCS協定,在SSL/TLS中必然不可能是完全獨立的,協定封裝上是獨立的,語義卻不可能是獨立的,否則,我在 ClientHello後發送一個CCS,可否?唉,心病還未痊愈,CCS又來搗亂,如果說心髒出血是OpenSSL的問題的話(它實際上是一個低級的代 碼級錯誤),CCS漏洞則是一個協定層面的問題,這個問題可不低級!我相信不止OpenSSL的實作會有這個問題。

       我不再吐嘈了,但是我想澄清網際網路時代系統兩種死法的不同之處,對于安全而已,死法也隻有兩種,我舉一個現實中的例子,一種是生病或中毒而死,一種是外力 置死,比如車禍,地震,或者被砍死,這兩種本質是不同的,第一種是你自身出了問題,第二種則是外部原因導緻。映射到網際網路,對于密碼被破解,CCS漏洞之 類的,這就是第一類的,這類問題一般都是系統本身的設計問題,而對于像棧溢出,Heartbleed,堆溢出之類的,則屬于第二類,這類問題一旦碰到,很 公平,但是不屬于系統設計的問題,隻是實作問題。再說一下現實世界,即便吃再安全的食品,也怕菜刀,但是可以請保镖,武夫之流能擋刀,但是最終可能會由于 吃了太多的不健康的油而緻癌...

       做個廣告,最好的篩子:OpenSSL

 本文轉自 dog250 51CTO部落格,原文連結:http://blog.51cto.com/dog250/1423638

繼續閱讀