分析TLS 1.3降级攻击以及主要TLS库中的漏洞

 

概述

在2018年11月30日,我们披露了CVE-2018-12404、CVE-2018-19608、CVE-2018-16868、CVE-2018-16869和CVE-2018-16870这五个漏洞,这些都是2018年8月在几个TLS库中发现的漏洞。

在5月15日,我找到了Yuval Yarom,与他讨论我在一些TLS实现中发现的问题。在此之后,我开始与Eyal Ronen、Robert Gillham、Daniel Genkin、Adi Shamir、Yuval Yarom展开合作,并由Eyal Ronen牵头。我们的研究成果已经在这里发表: https://eprint.iacr.org/2018/1173 。正如大家所看到的那样,目前RSA的发明者本人建议大家在TLS中弃用RSA。

我们针对9种不同的TLS实现,尝试进行了缓存攻击测试,测试结果表明,其中7种TLS实现易受攻击,它们分别是:OpenSSL、Amazon s2n、MbedTLS、Apple CoreTLS、Mozilla NSS、WolfSSL和GnuTLS。BearSSL(由我的同事Thomas Pornin开发)和Google的BoringSSL经测试是安全的,因此还剩下两员大将,并没有全军覆没。

我们的攻击方式是针对这些实现的缓存访问时序利用侧信道泄漏,从而攻破TLS实现的RSA密钥交换。从多个角度来看,这次的攻击都很有意思(在这里先不提它影响了许多主要的TLS实现):

1、该攻击影响所有版本的TLS(包括TLS 1.3)和QUIC。后面版本的TLS甚至不提供RSA密钥交换。由于这是对TLS 1.3目前唯一的已知降级攻击,因此还是非常关键的。

2、该攻击使用了最新的缓存攻击技术。其中所使用的技术包含Flush+Reload攻击、Prime+Probe攻击和分支预测(Branch-Predition)技术。

3、该攻击效果非常显著。我们找到了一种方法,能够针对任何浏览器进行攻击,减慢其中一些浏览器的运行速度,或者使用长尾分布(Long Tail Distribution)重复尝试攻破会话(Session)。我们甚至利用了格子框架(Lattices)来加速这一攻击过程。

4、针对RSA PKCS#1 v1.5利用Manger和Ben-Or的攻击方式。你听说过Bleichenbacher的百万条消息攻击吗?实际上,我们发现了一种更好的攻击方式。我们针对RSA PKCS#1 v1.5利用Manger的OAEP攻击和Ben-Or提出的算法,这种算法比1998年Bleichenbacher提出的方法要更加有效。我在这里上传了部分代码: https://github.com/mimoo/RSA_PKCS1v1_5_attacks

要了解有关该研究的更多信息,请阅读我们的白皮书: http://cat.eyalro.net/ 。在本文中,我将主要讨论协议级别的漏洞利用。

 

RSA攻击方法的起源

尽管Ben-Or等人的研究最初是作为支撑RSA安全性的证据,但在他们的研究成果中,还概述了针对协议的攻击方式。十五年后,在1998年,Daniel Bleichenbacher发现了一种Padding Oracle攻击方法,并设计了一种针对RSA的独特而实际的攻击方式。其后果十分严重,大多数TLS实现都有被攻击的风险,因此人们又提出了一些缓解措施,旨在防范Daniel提出的攻击方式。经过人们不断的研究,又有一系列攻击方法被接连提出,人们开始意识到,要针对所有攻击方法实现缓解并不是一件易事:

1、Bleichenbacher(CRYPTO 1998),也被称为百万消息攻击、BB98、针对PKCS#1 v1.5的Padding Oracle攻击:

http://archiv.infsec.ethz.ch/education/fs08/secsem/bleichenbacher98.pdf

2、Klima(CHES 2003):

https://eprint.iacr.org/2003/052

3、Bleichenbacher提出的第二种攻击方法:在XML加密中攻破PKCS#1 v1.5:

https://www.nds.rub.de/media/nds/veroeffentlichungen/2012/12/19/XMLencBleichenbacher.pdf

4、Degabriele团队(CT-RSA 2012):

https://eprint.iacr.org/2011/615.pdf

5、Bardou团队(CRYPTO 2012):

https://eprint.iacr.org/2012/417

6、PaaS云中跨租户侧信道攻击(CCS 2014):

https://www.cs.unc.edu/~reiter/papers/2014/CCS1.pdf

7、重新审视SSL/TLS实现:新的Bleichenbacher侧信道攻击(USENIX 2014):

https://www.usenix.org/conference/usenixsecurity14/technical-sessions/presentation/meyer

8、论TLS 1.3和QUIC的安全性以及PKCS#1 v1.5加密的弱点(CCS 2015):

https://www.nds.rub.de/media/nds/veroeffentlichungen/2015/08/21/Tls13QuicAttacks.pdf

9、DROWN(USENIX 2016):

https://drownattack.com/

10、Bleichenbacher的Oracle威胁的回归(USENIX 2018):

https://robotattack.org/

11、密钥重用的风险:对Ipsec IKE的实际攻击(USENIX 2018):

https://www.usenix.org/system/files/conference/usenixsecurity18/sec18-felsch.pdf

让我们来面对现实,开发人员提出的缓解措施其实是不切实际的。此外,我们发现,尝试缓解此类攻击的实现实际上有助于攻击。这一点非常好笑。

我今天所讨论的研究成果,可以被视为这些“重新发现”的其中之一。我前老板的老板(Scott Stender)曾跟我说:“你可以写出针对某个领域的第一篇论文、最好的一篇论文,或者是最后一篇论文。”我们肯定不是第一篇,好不好也不知道,但我们肯定是希望能成为最后一篇。

 

RSA和TLS

简而言之,SSL/TLS(除1.3版本之外)可以在握手期间使用RSA密钥交换来协商共享秘钥(Shared Secret)。RSA密钥交换非常简单:客户端使用服务器的RSA公钥加密共享秘钥,然后服务器接收并对其进行解密。如果我们可以通过某种攻击方式来解密此值,那么我们就可以被动地解密会话(例如:获取Cookie),或者我们可以主动地模仿其中一端。

 

实践篇:攻击浏览器

我们使用BEAST攻击模型(与目标服务器共存以进行缓存攻击),我此前已经在视频中对这种攻击方式进行过解释:

https://cryptologie.net/article/413/beast-an-explanation-of-the-cbc-attack-on-tls/

在此之后,我们尝试解密目标客户端(Bob)和bank.com之间的会话:我们可以通过一些JavaScript内容为他提供服务,这些JavaScript内容将会在bank.com上不断尝试新的连接。如果没有尝试新的连接,那我们可以通过使当前的连接失败来强制进行,因为我们处在一个中间人的位置。

为什么会有几个连接,而不是一个?因为大多数浏览器(除了我们可以欺骗的Firefox之外)都会在一段时间后(通常是30秒)返回超时。如果两个对等体之间协商RSA密钥交换,那么没问题,我们可以持续等待对协议进行被动攻击。但如果两个对等体未协商RSA密钥交换,那么我们就需要主动攻击会话,从而实现降级或伪造服务器的RSA签名(稍后会详细介绍)。这需要时间,因为攻击过程要求我们向服务器发送数千条消息。这一攻击也可能会失败。但是,如果我们可以多次尝试,经过几次实验后,成功的概率也会随之上升。因此,这就是我们不断向bank.com发送连接尝试的原因。

 

攻击TLS 1.3

有两种攻击TLS 1.3的方法。在每次攻击中,服务器也需要支持旧版本的协议。

第一种方法依赖于以下事实:当前服务器的公钥是RSA公钥,用于在握手期间签名临时密钥,以及服务器支持的旧版本TLS重用相同的密钥。

第二种方法依赖于以下事实:两个对等体都支持具有支持RSA密钥交换的Cipher Suite的旧版本TLS。

尽管TLS 1.3不使用RSA加密算法进行密钥交换,但它确实使用了RSA的签名算法。如果服务器的证书包含RSA弓腰,那么它将会用于在握手期间对其短暂的公钥进行签名。TLS 1.3客户端可以在RSA和RSA-PS之间通告它想要支持的RSA签名算法(如果存在)。由于大多数TLS 1.2服务器已经支持RSA,,因此大多数服务器会重新使用其证书,而不是更新到最近的RSA-PSS。根据标准指定的RSA数字签名非常接近于同一文档指定的RSA加密算法,因此Bleichenbacher对RSA加密算法的解密攻击也非常接近于伪造RSA签名。从直觉上来看,我们已经有了pmse和解密攻击方法,可以允许我们找到(pms^e)^d=pms。我们可以假设要签名的内容tbs(参考RFC 8446)为tbs = pmse,并通过攻击获得tbsd,根据定义来看,它是消息tbs的签名。然而,这种签名伪造方式需要在传统Bleichenbacher攻击的基础之上附加额外的步骤(盲操作)。在实际中,可能会产生数十万条额外的消息。

在此前( https://drownattack.com/ ),我们已经展示了密钥重用的方法,可以允许针对TLS进行复杂的跨协议攻击。实际上,我们可以通过与同一服务器协商先前版本的TLS,成功伪造我们自己的握手记录签名(包含在CertificateVerify消息中)。如果新的连接使用相同的RSA密钥证书来进行密钥交换,那么就将暴露其长度或允许Bieichenbacher Oracle攻击。

 

降级至TLS 1.2

每个TLS连接都以协商TLS版本和其他连接属性开始。由于新版本的TLS(1.3)不提供RSA密钥交换,因此我们要想利用这种攻击方式,必须先降级到较旧版本的TLS。TLS 1.3是相对较新的(2018年8月),支持它的大多数服务器也都支持旧版本的TLS(它们都支持RSA密钥交换)。因此,不支持TLS 1.3的服务器将使用较旧版本TLS(在我们的示例中为TLS 1.2)serverHello消息进行响应。

要降级客户端的连接尝试,我们可以简单地进行服务器欺骗(Spoof)。除了协议降级之外,还有其他技术能够迫使浏览器客户端回退到较旧的TLS版本,包括:网络故障、欺骗性TCP RST数据包、缺少响应等。请参见POODLE: https://www.openssl.org/~bodo/ssl-poodle.pdf

继续使用欺骗性的TLS 1.2握手,我们可以简单地在ServerCertificate消息中显示服务器的RSA证书,然后使用ServerHelloDone消息结束握手。此时,如果服务器没有允许RSA密钥交换的可信证书,或者客户端拒绝支持RSA密钥交换,或者使用了比TLS 1.2更早的版本,那么就都将会停止攻击。否则,客户端使用证书中包含的RSA公钥来加密TLS预备主秘钥(TLS Premaster Secret),将其发送到ClientKeyExchange消息中,并使用ChangeCipherSpec和Finished消息结束其握手部分。

此时,我们需要执行攻击,以解密RSA加密的预备主秘钥。我们发送的最后一条Finished消息中必须包含整个记录的认证标志(使用HMAC),此外还使用从预备主秘钥派生出来的传输密钥(Transport Keys)进行加密。尽管有些客户端没有握手超时这一设置,但如果我们的响应花费太久时间,大多数严格的应用程序(例如浏览器)都会放弃连接的尝试。尽管看起来这种攻击只需要几千条消息,但在实际上可能数量还是太多。但幸运的是,有几种技术能帮助我们减慢握手的速度:

1、发送可能重置客户端计时器的ChangeCipherSpec消息;

2、发送TLS警告来重置握手计时器。

一旦解密攻击被终止,我们就可以将预期的Finished消息发送给客户端并完成握手。在那里,一切皆有可能,从被动观察消息到模拟服务器,再到主动篡改其请求。这种降级攻击绕过了多个降级缓解措施:一个服务器端和两个客户端。协商旧版TLS的TLS 1.3服务器必须将此信息通告给它的对等体。这是通过将ServerHello消息中server_random字段的四分之一字节设置为已知值来实现的( https://tools.ietf.org/html/rfc8446#section-4.1.3 )。最终协商旧版TLS的TLS 1.3客户端必须检查这些值是否存在,如果找到就要中止握手。但正如RFC中所述,“当使用静态RSA时,不会提供降级保护。”由于我们更改了这个值并删除了警告的字节,所以客户端没有机会检测到我们的攻击。另一方面,最终回到旧版本TLS的TLS 1.3客户端必须在其后续客户端中通告此信息( https://tools.ietf.org/html/rfc7507 ),因为我们冒充了服务器,所以就可以忽略此警告。此外,客户端还包括加密的预备主秘钥的client hello使用的版本。由于和上面相同的原因,这种缓解对我们的攻击没有影响。目前,RSA是对TLS 1.3唯一的已知降级攻击,我们是第一个成功对此研究成果进行漏洞利用的研究人员。

 

攻击TLS 1.2

与之前的攻击一样,客户端和目标服务器都需要支持RSA密钥交换。由于这是典型的密钥交换,大多数已知的浏览器和服务器都对其支持,尽管它们通常更喜欢使用Elliptic Curve或Finite Field Diffie-Hellman密钥交换来协商前向密钥交换。这是在前两次握手消息期间作为Cipher Suite的一部分完成的。为了避免这种结果,我们可以拦截并修改ClientHello消息,避免在进行任何非RSA的密钥交换。然后,服务器就会仅从一组基于RSA密钥交换的Cipher Suite中进行选择,这允许我们执行前文所述的攻击。我们对ClientHello消息的修改,只能通过完成消息验证正确的握手记录来检测,但由于我们控制了这一消息,所以可以伪造想要的标志。

另一方面,如果两个对等体最终都在自行协商rSA密钥交换,我们可以被动地观察连接,并花费时间来攻破会话。

 

总结

对于每一个发现的漏洞,实际上都有三种论文:最早披露的论文、关于该漏洞的最佳说明、最后一篇论文。我们希望这篇能够成为最后一篇论文。在1998年Bleichenbacher研究了RSA PKCS#1 v1.5加密方案的安全性之后,20年来,人们不断尝试新的攻击思路。尽管我们的文章中推荐了一系列的缓解方案,但现在是时候宣布:我们不建议使用RSA PKCS#1 v1.5,而建议选择更加现代的方案,例如非对称加密的OAEP和ECEIS,或者用于密钥交换的Elliptic Curve Diffie-Hellman。最后,我们注意到TLS的无密钥实现(Keyless)是一个有吸引力的目标,但由于是闭源的,因此我们在此次分析中没有涉及。

(完)