TLS 攻击之POODLE

转载 http://www.bewindoweb.com/272.html,具体实例分析,写的很好,然后文章我加入了自己的理解。

一、 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 v3.0以下

防御方法:完全禁用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密码块链接模式——加密

1598950607286

(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字节的一组,那么需要进行填充,例如(前面字符没有用十六进制表示):

1598950619500

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

(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密码块链接模式——解密

1598950639436

加密的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 攻击

2.3.1 攻击原理

1599017277323

攻击最终原理:

目标:已知IV,密文。求中间值。

方法:

通过逐字节伪造IV使得:
$$
伪造IV+中间值=0x01(明文)
$$
(因为服务器端会进行padding校验,回显成功与否,这里用的padding是pkcs#5)

然后利用:
$$
0x01(明文)+真实IV=中间值
$$
即可求得中间值,从而通过下列等式求得明文。
$$
真实IV+中间值=明文
$$

2.3.2 攻击过程


首先请注意,始终在字符串的末尾附加至少一个填充字节,因此将使用0x01填充7字节的值(如AVOCADO),而将8字节的值(如PLANTAIN)具有向其中添加了完整的填充块。填充字节的值还指示字节数,因此逻辑上最后一个密文块末尾的逻辑最终值必须是:

  • 单个0x01字节(0x01)
  • 两个0x02字节(0x02、0x02)
  • 三个0x03字节(0x03、0x03、0x03)
  • 四个0x04字节(0x04、0x04、0x04、0x04)
  • …等等

如果最终的解密块未以这些有效字节序列之一结尾,则大多数密码提供程序将抛出无效的填充异常。引发此异常的事实对于攻击者(我们)而言至关重要,因为它是填充预言攻击的基础

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

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

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

  • 收到有效的密文(正确填充并包含有效数据的密文)后,应用程序将正常响应(200 OK)

  • 收到无效的密文(解密后不会以有效填充结尾)时,应用程序将引发加密异常(500 Internal Server Error)

  • 收到有效的密文(正确填充的密文)但解密为无效值时,应用程序将显示自定义错误消息(200 OK)

    上面描述的场景是经典的Padding Oracle,因为我们可以使用应用程序的行为轻松确定提供的加密值是否正确填充。术语oracle是指可以用来确定测试通过还是失败的机制。

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

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

1598950652145

此时必然产生了1位填充(因为我们已经知道IV是0x01、0x02、0x03、0x04、0x05、0x06、0x07、0x08),最多尝试次数为256次。(这里最后一位必须为01才可以通过服务器的padding校验,因为采用的是PKCS5标准填充

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

1598950673196

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

1598950689577

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

1598950705091

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

img

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

三、POODLE攻击原理

3.1 SSLv3.0存在的问题

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

加密类型加密方式
块加密 Block CipherIDEA
块加密 Block CipherRC2-40
块加密 Block CipherDES-40
块加密 Block CipherDES
块加密 Block Cipher3DES
块加密 Block CipherFORTEZZA
流加密 Stream CipherRC-40
流加密 Stream CipherRC4-128

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

1598952050289

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

img

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

img

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

img

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

0x07= g(0x07)0x01  => g(0x07) = 0x06

现在要求:(此时要注意不是拿0x6E ⊕ g(0x07密),因为如果解密第四块,应该是第三块 最后一字符⊕g(0x07密))

x = 0x6Eg(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攻击。

4 解决方法

禁用SSL 3.0协议(ssl version ssl3.0 disable)。

4.1 服务端禁用方法

(1)Apache 2.x:
在mod_ssl配置文件中使用如下命令禁用SSLv2和SSLv3:
SSLProtocol All -SSLv2 -SSLv3
重启Apache

(2)Nginx:
在配置文件中使用:
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
重启Nginx

(3)lighttpd:
确认lighttpd为1.4.29及以上版本
在配置文件中使用
ssl.use-sslv3 = “disable”
重启lighttpd

(4)tomcat参考:

https://tomcat.apache.org/tomcat-6.0-doc/ssl-howto.html

https://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html

(5)IIS:
查找如下注册表项:
HKey_Local_MachineSystemCurrentControlSetControlSecurityProviders SCHANNELProtocols
该注册表项通常包含以下子项:

  • PCT 1.0
  • SSL 2.0
  • SSL 3.0
  • TLS 1.0
    每个注册表项都保留适用于该项的协议相关信息。可以在服务器上禁用这些协议中的任一种。为此,

请在协议SSL 3.0的服务器子项中创建一个新的DWORD值。名称为Enabled,将DWORD值设置为“00 00 00 00”。 重启IIS服务

4.2 浏览器禁用方法

(1)IE:
“工具” -> “Internet 选项” -> “高级” ,取消”使用 SSL 3.0”的复选框。
(2)Chrome:

复制一个平时打开 Chrome 浏览器的快捷方式,在新的快捷方式上右键点击,进入属性,
在”目标”后面的空格中字段的末尾输入以下命令 –ssl-version-min=tls1
(3)FireFox:

在地址栏输入”about:config”,然后将 security.tls.version.min 调至 1。

参考资料

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

2、《Padding Oracle》

3、[《百度百科:Padding Oracle》](https://baike.baidu.com/item/Padding Oracle/3530091?fr=aladdin)

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研究报告原文

11 https://www.onebug.org/%E7%BB%BF%E7%9B%9F%E6%BC%8F%E6%B4%9E%E5%BA%93/87280.html :预防办法

文章目录
  1. 一、 POODLE简介
  • 二、Padding Oracle 攻击原理
    1. 2.1 CBC密码块链接模式——加密
    2. 2.2 CBC密码块链接模式——解密
    3. 2.3 Padding Oracle 攻击
      1. 2.3.1 攻击原理
      2. 2.3.2 攻击过程
  • 三、POODLE攻击原理
    1. 3.1 SSLv3.0存在的问题
    2. 3.2 利用SSL漏洞进行POODLE攻击
    3. 3.3 Padding验证和MAC验证返回结果不同的情况
    4. 3**.4 POODLE中“降级”的体现**
  • 4 解决方法
    1. 4.1 服务端禁用方法
    2. 4.2 浏览器禁用方法
  • 参考资料