文章目录

前言

各大浏览器、操作系统都屏蔽掉了SSLv2.0、SSLv3.0,原因是“不安全”,我们来分析SSL v3.0为什么不安全。

一、 POODLE简介

2014年9月Google的一份研究报告《This POODLE Bites: Exploiting The SSL 3.0 Fallback》指出,SSL存在安全漏洞CVE­-2014-3566,代号为POODLE(Padding Oracle On Downgraded Legacy Encryption,基于降级旧加密协议的填充提示),该漏洞可以使得攻击者获取到一段明文数据,比如HTTP的cookie,且除了完全禁用SSL,或者利用TLS_FALLBACK_SCSV字段禁止协议降级到SSL,没有其他更好的手段可以防御。

二、Padding Oracle 攻击原理

Padding Oracle是Web程序渗透的经典攻击方式,由Juliano Rizzo和Thai Duong于2010年《Practical Padding Oracle Attacks》提出,该攻击利用CBC(Cipher-block chaining,密码块链接模式)加密模式中的填充漏洞给出的提示信息逐步推导出明文数据。

2.1 CBC密码块链接模式——加密

(1)对明文进行分组,每组长度相同(一般为8字节或16字节),对长度不足的分组需要进行填充(Padding)。

填充通常遵循的是PKCS5标准,即填充的字符是需要填充字符的个数。

例如,这里的明文字符串为“GET /a HTTP/1.1\r”,那么按ASCII的十六进制就可以表示为:

  • 第一组明文:“0x47、0x45、0x54、0x20、0x2F、0x61、0x20、0x48”
  • 第二组明文:“0x54、0x54、0x50、0x2F、0x31、0x2E、0x31、0x0D”

假设后面还有字符不能构成8字节的一组,那么需要进行填充,例如(前面字符没有用十六进制表示):

当然,一般不会有全填充的组。

(2)随机生成一个初始化向量IV,与第一个明文分组进行异或运算得到中间值(Intermediary Value)。

例如这里随机生成的IV为“0x01、0x02、0x03、0x04、0x05、0x06、0x07、0x08”,与第一个分组“0x47、0x45、0x54、0x20、0x2F、0x61、0x20、0x48”进行异或后得到“0x46、0x47、0x57、0x24、0x2A、0x67、0x27、0x40”。

(3)将异或结果进行加密,得到第一个明文分组的密文。

一般会使用密钥(key)加密,这里简单假设密钥加密效果等同于加密函数y = f(x) = x + 1,那么可以得到第一组密文“0x47、0x48、0x58、0x25、0x2B、0x68、0x28、0x41”。

(4)从第二个明文分组开始,将上一组密文当作IV,进行异或运算,再进行加密,得到该组密文。

例如这里由第一组密文“0x47、0x48、0x58、0x25、0x2B、0x68、0x28、0x41”与第二组明文“0x54、0x54、0x50、0x2F、0x31、0x2E、0x31、0x0D”进行异或,得到“0x13、0x1C、0x08、0x0A、0x1A、0x46、0x19、0x4C”,再进行相同加密,得到“0x14、0x1D、0x09、0x0B、0x1B、0x47、0x1A、0x4D”,这就是第二组密文。

2.2 CBC密码块链接模式——解密

加密的IV是随机生成的,而解密则必须使用这个IV。

(1)对密文进行分组,每组长度相同(一般为8字节或16字节)。

例如这里将密文分为了两组:

  • 第一组密文:“0x47、0x48、0x58、0x25、0x2B、0x68、0x28、0x41”
  • 第二组密文:“0x14、0x1D、0x09、0x0B、0x1B、0x47、0x1A、0x4D”

(2)对密文进行解密,得到中间值。

一般使用密钥,同样的这里假设密钥效果等同于函数x = f(y) = y - 1

  • 第一组中间值:“0x46、0x47、0x57、0x24、0x2A、0x67、0x27、0x40”
  • 第二组中间值:“0x13、0x1C、0x08、0x0A、0x1A、0x46、0x19、0x4C”

(3)使用初始化向量IV,与第一个分组进行异或运算得到第一组明文。

这是利用异或的性质:a⊕b=c,a⊕c=b,b⊕c=a,所以无论如何异或都能得到唯一的第三个数。

例如这里IV为“0x01、0x02、0x03、0x04、0x05、0x06、0x07、0x08”,第一个数0x01与第一组第一个中间值0x46异或结果为0x47,就是明文“G”的ASCII十六进制表示,于是得到第一组明文“0x47、0x45、0x54、0x20、0x2F、0x61、0x20、0x48”

(4)从第二组开始,依次将前一组密文和该组中间值异或,得到该组明文。

例如第一组密文“0x47、0x48、0x58、0x25、0x2B、0x68、0x28、0x41”和第二组中间值“0x13、0x1C、0x08、0x0A、0x1A、0x46、0x19、0x4C”异或得到第二组明文“0x54、0x54、0x50、0x2F、0x31、0x2E、0x31、0x0D”。

值得注意的是,解密可以并行计算,因为密文都是已经获取好的;加密则不行,因为前一组密文必须要计算出来。

2.3 Padding Oracle 攻击

现在假设密文仍然是上述字段“GET /a HTTP/1.1\r”,且用户连接到的是公共WIFI,攻击者可以通过抓包获取CBC密文以及初始化向量IV(当然要把IV明文传给服务器否则服务器无法解密第一个分组)。

我们现在希望通过密文和IV获取明文,由于“IV⊕中间值=明文”,问题转变为如何求IV对应的中间值。

我们知道,对大多数Web服务器而言:

  • 如果参数解密成功,且数据合法,返回HTTP 200 OK,提示成功
  • 如果参数解密成功,但数据非法,返回HTTP 200 OK,提示非法,或Rest风格接口会返回HTTP 400 Bad Request,提示非法
  • 如果参数解密失败,服务器将抛出异常,返回HTTP 500 Internal Server Error

这给攻击者提供了判断依据:

  • 如果提示HTTP 200或HTTP 400,说明解密成功;
  • 如果提示HTTP 500,说明解密失败。

IV出现在解密的最后一步,而且是可以构造的,那么攻击者可以通过构造特殊的IV,直到符合“填充”规则通过解密流程(虽然不一定能通过数据合法性校验),具体而言:

(1)构造“0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00”的特殊IV发送给服务端,不断尝试递增最后一位并发送给服务端,直到服务端解密成功。

此时必然产生了1位填充(因为我们已经知道IV是0x01、0x02、0x03、0x04、0x05、0x06、0x07、0x08),最多尝试次数为256次。

(2)计算出末位中间值,其值等于伪造向量末位异或0x01:0x41⊕0x01=0x40

(3)利用原始向量末位值异或中间值,得到明文0x48,即字符“H”:0x40⊕0x08=0x48

(4)利用中间值计算出末位为0x02的伪造向量应有值:0x40⊕0x02=0x42

(5)通过改变倒数第二位,直到生成0x020x02的末位明文填充字符,符合2位填充规则,然后类似地推测倒数第二位的中间值:

重复上述步骤,就能够得到完整的明文信息,这就是Padding Oracle 填充提示攻击。

三、POODLE攻击原理

3.1 SSLv3.0存在的问题

SSLv3.0的记录层可以使用如下加密方式:

 加密类型  加密方式
 块加密 Block Cipher IDEA 
 块加密 Block Cipher RC2-40
 块加密 Block Cipher DES-40
 块加密 Block Cipher DES
 块加密 Block Cipher 3DES
 块加密 Block Cipher FORTEZZA
 流加密 Stream Cipher RC-40
 流加密 Stream Cipher RC4-128

流加密这里不讨论,也是有安全问题,主要讨论CBC块加密。

SSL记录层加密的是原始数据+MAC(消息验证码)信息摘要+填充字节,MAC一般是Hash值,SSLv3.0中MAC通常为20字节。也就是说,SSL先对数据做完整性校验,再进行CBC加密。在CBC解密的一端(服务器),SSL没有规定padding填充块字节内容,只校验填充块最后一个字节,该字节为填充长度,然后去掉填充的字符,再进行MAC验证,最后获得明文数据。

  • 先校验完整性,再加密,使得对端收到数据后先解密,后校验完整性,解密是否成功为攻击提供了判断依据;
  • 只验证填充块的最后一个字节,因此填充块可以填充任意字符,且最后字符固定使得攻击者可以利用类似Padding Oracle的攻击机制。

我们可以利用类似前面Padding Oracle的思路,将要解密的字符放到最后一个块末尾,不断地调整前一个IV的值(可能是初始化向量,也可能是前一段的密文,并且无论是哪个攻击者都是知道的),直到成功通过解密,此时明文必定为0x07或0x15(16字节一块的话),最多尝试256次(或512次),就能够通过服务器验证,从而推导出对应的中间值,然后利用该中间值和IV推导出明文。这期间不用担心修改IV导致MAC校验失败,因为那是CBC解密之后的事情。

3.2 利用SSL漏洞进行POODLE攻击

假设攻击者B代理了客户端A的HTTPS访问服务器C的请求,可以截获到SSL密文数据以及SSL握手阶段的IV,且可以通过A去发送HTTPS请求,此时如果A没有退出登录,都会自动携带上Cookie。这样,B可以控制A发送的HTTP请求中的请求路径Path和请求体Body,并通过调整Path和Body,让A发出的请求满足两个条件:

  • 填充字段恰好填充了一个块长度
  • Cookie的第一个未知字符刚好出现在前面某个块的末尾

例如,加密采用3DES,8字节一个块,且SSL上层为HTTP协议,发送的明文为:

GET / HTTP/1.1\r\nCookie: abcdefgh \r\n\r\nXXXX MAC数据 XXXXXX7

MAC数据可能并不是刚好8字节,不过无所谓。攻击者并不知道明文,但知道Cookie密文的位置,知道此时想要解密的cookie的最后一个字符在第4个块末尾。然后攻击者将整个块的密文复制到最后一个填充块密文上:

然后不断调整前一块(MAC数据)对应密文位置的值,直到通过解密校验,根据SSL的漏洞,此时最后一块最后一个值必然为0x07:

这里例子举得不好,0x07密文也是0x07,后面用0x07明、0x07密来区分,此时我们假设未知加密函数为f(x),其逆为g(y),那么根据CBC解密流程,有:

0x07明 = g(0x07密) ⊕  0x01  => g(0x07密) = 0x06

现在要求:

x = 0x6E ⊕ g(0x07密)

因此x = 0x68,即字符"h",得到解密明文"h"。

同理,通过控制请求路径,例如GET /a、GET /aa,不断地把已经解密的Cookie字符挤出,把未知字符留在该块末尾,然后循环进行前述操作,即可得到完整的Cookie字段。

3.3 Padding验证和MAC验证返回结果不同的情况

前面的操作都是建立在Padding验证和MAC验证返回结果不同的基础之上,如果返回结果相同,那么MAC会校验不过导致失去判断Padding验证成功的依据。此时攻击者需要利用响应时间的差异来进行判断。如果响应时间仍然相同,那么这种攻击就无效了。

​3.4 POODLE中“降级”的体现

POODLE只在SSLv3.0以下版本才容易攻击成功,TLS会检查填充字符,所以TLS构造的padding通过服务器验证概率极低,TLSv1.3以后则完全避免了该漏洞。2014年,TLS已经得到广泛应用,但不乏少数服务器、客户端(比如IE6)和中间网络设备仍然采用SSL协议。因此为了平滑过渡增加用户体验,TLS1.2、TLS1.1、TLS1.0协议实现都会向后兼容SSLv3.0协议,最终协商通信协议为服务端和客户端支持的最高版本协议。如果记录协议中采用的是RC4流加密或者CBC模式的块加密,那么攻击者就可以进行POODLE攻击。

参考资料

1、《Web狗要懂的Padding Oracle攻击》:很详细

2、《Padding Oracle》

3、《百度百科:Padding Oracle》

4、《ASCII表》在线异或计算器:便于实验

5、《HTTPS 协议降级攻击原理》:对攻击原理理解透彻

6、《CVE-2014-3566 SSLv3 POODLE原理分析 – insight-labs》:有些许理解错误,注意辨别

7、《POODLE attacks on SSLv3 (14 Oct 2014)》:英文原文例子

8、《漏洞分析---SSLv3降级加密协议Padding Oracle攻击(POODLE)技术分析》:例子详细

9、《SSLv3 POODLE 攻击分析》:最正确的一篇分析

10、《This POODLE Bites: Exploiting The SSL 3.0 Fallback》:Google研究报告原文


转载请注明出处http://www.bewindoweb.com/272.html | 三颗豆子
分享许可方式知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议
重大发现:转载注明原文网址的同学刚买了彩票就中奖,刚写完代码就跑通,刚转身就遇到了真爱。
你可能还会喜欢
具体问题具体杠