接着上一篇《Padding Oracle原理深入剖析与实践》,我们继续看。
在上一篇文章的结尾,我留下了两个思考问题:
1、Padding Oracle漏洞除了能够产生明文猜解的问题,还会产生哪些风险呢?
2、ZeroPadding和NoPadding还会存在Padding Oracle风险吗?
第一个问题答案,就是我们本篇主要讨论的内容:CBC字节翻转攻击。 第二个问题,我也会在最后给出解答。
0x01 字节翻转控制解密结果
CBC字节翻转攻击是Padding Oracle漏洞利用的另一种方式。攻击者不仅可以在不知道秘钥的情况下猜解出明文,还可以控制明文,在不知道秘钥的情况下构造出任意内容,控制解密结果。
上一篇对Padding Oracle的讲解中,我们定义了一个Zeroing_IV,便于我们理解每次迭代是如何控制最后几位Padding值的。
因为
Zeroing_IV ⊕ DEC_key = 00000000000000000000000000000000
仍然参照这张图:
所以我们如果想让plaintext block1 最后几位是某个Padding值,只需要将这个值与Zeroing_IV异或即可。比如我们想让最后2位是0x03,也就是前面文章中猜解倒数第三个字符的时候,我们计算了:
IV = Zeroing_IV ⊕ 0x03 = 00000000000000000000000000001c79 ⊕ 0x03 = 00000000000000000000000000001f7a
即可得到想要的IV值。这个过程实际上就是在控制解密结果。
理解了这块,CBC字节翻转攻击就很容易理解了。
通过前面的过程,我们得到了完整的 Zeroing_IV:
Zeroing_IV = 967d248cf93924b45b0d83f705e81c79
假设在某个Web服务里,这段密文是用来传递当前登录用户身份的(比如说这是在cookie中传递的一段密文)。如果我想让服务端接收到密文解密后的明文由原来的内容变成admin,那么我就可以用“admin”+11个0x0b拼接在一起,与Zeroing_IV异或,作为新的IV和加密块传给服务端。
(Zeroing_IV ⊕ DEC_key) ⊕ 目标值 = 00000000000000000000000000000000 ⊕ 目标值
所以
(Zeroing_IV ⊕ 目标值) ⊕ DEC_key = 目标值
在我上面举的例子里,“admin”+11个0x0b 的hex值为:
61646d696e0b0b0b0b0b0b0b0b0b0b0b
与Zeroing_IV(967d248cf93924b45b0d83f705e81c79)异或,得到:
967d248cf93924b45b0d83f705e81c79 ⊕ 61646d696e0b0b0b0b0b0b0b0b0b0b0b = f71949e597322fbf500688fc0ee31772
将结果与ciphertext block 1:fcc1b431b32bc2d5f0f290dd64df1a3f 拼接得到:
f71949e597322fbf500688fc0ee31772fcc1b431b32bc2d5f0f290dd64df1a3f
可以作为参数值传给我们的/decrypt接口测试一下:
http://localhost:8083/decrypt?ct=f71949e597322fbf500688fc0ee31772fcc1b431b32bc2d5f0f290dd64df1a3f
解密内容成功控制为admin。
0x02 只能控制某一个分组?
看起来我们不仅可以通过Padding Oracle破解到明文,还能通过字节翻转控制明文内容。但是别高兴的太早。
仔细想想,上面这个CBC字节翻转攻击Demo其实有个缺陷,就是在一段多个分组的密文中,我们无法完整控制整个密文的解密结果。除了第一组明文,想要控制其他任意一组明文,都要篡改上一组的密文,那么也就会对上一组的解密结果产生影响。
比如说有一段明文可以分成三个分组。
{"username":"w4ter0","role":"guest"}
{"username":"w4t | er0","role":"gue | st"}
拆分之后的明文:
P1:{"username":"w4t
P2:er0","role":"gue
P3:st"}
还是用我们上一篇中用过的初始IV和密钥计算出密文:
http://localhost:8083/encrypt?pt={"username":"w4ter0","role":"guest"}
得到:e14950e98b0904dd282de280609b7314eadd0b446a