概述
继之前爆出的“心脏出血”漏洞后,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起,这个漏洞就一直存在。
OpenSSL里正常握手过程中,客户端和服务端的消息交换式按照下图流程进行的(参照RFC5246 The Transport Layer Security (TLS) Protocol Version 1.2 §7.3)。
如图,在握手阶段需要两次发送ChangeCipherSpec消息,OpenSSL也确实是按照正确的时间发送CCS,然而,CCS消息却可以在其他时间里被接收。攻击者就可以利用这一行为解密或者修改传输通道里的数据。
发现漏洞有多难
造成CCS漏洞16年没有被发现的原因是OpenSSL实现缺少全面的代码审查(code reviews)。如果审查者有一定的TLS和SSL开发经验,那么他们就应该能自己发现这个问题。
模糊测试也许很有效,但历史经验表明,拥有TLS/SSL开发经验对发现OpenSSL安全问题尤为重要:
CVE-2004-0079漏洞
CVE-2004-0079是Codenomicon发现CCS漏洞,也是第一个CCS漏洞。 之后Fix null-pointer assignment in do_change_cipher_spec() revealed被加入到OpenSSL中以修补这个漏洞。这个方法保证了CCS只在有新的密码产生后才被接收,然而这个新的密码在服务器端请求连接是就产生了,所有该方法并不能真正地防止CCS注入。
CVE-2009-1386漏洞
DTLS: SegFault if ChangeCipherSpec is received before ClientHello这个漏洞是因为在DTLS握手阶段太早地接收CCS消息,造成了分段错误。针对CCS时序验证也并没有很好滴被解决。
DTLS fragment retransmission bug
OpenSSL的第 #1950 补丁修改了带漏洞。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漏洞!
第一次翻译,有什么不当之处,希望指出。
最后
以上就是精明画板为你收集整理的OpenSSL严重安全漏洞CCS的全部内容,希望文章能够帮你解决OpenSSL严重安全漏洞CCS所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复