Padding Oracle Attack 讲讲
攻击的核心原理
要理解这个攻击,我们首先需要了解几个关键概念:
1. 分组密码和 CBC 模式
- 分组密码将明文分割成固定大小的分组进行加密
- CBC(密文分组链接)模式是一种常用的分组密码模式。在 CBC 模式中,每个明文分组在加密前,会先与前一个密文分组进行异或(XOR)运算。这使得每个密文分组都依赖于其之前的所有分组,从而提供了更好的安全性
- IV(初始化向量):第一个明文分组加密时没有前一个密文分组,因此需要一个初始化向量(IV)来代替
2. 填充(Padding)
为了确保最后一个明文分组能够填满整个分组长度,需要进行填充。例如,如果分组大小是 16 字节,而最后一个明文分组只有 13 字节,就需要填充 3 个字节。 PKCS#7 填充是常用的填充标准。它将填充的每个字节都设置为填充的长度。例如,如果需要填充 3 个字节,就会在明文末尾添加 0x03 0x03 0x03
。解密后,系统会检查最后一个字节的值,并移除相应数量的填充
攻击的步骤
Padding Oracle Attack 利用的就是填充验证机制的漏洞。攻击者通过发送修改后的密文到服务器,并观察服务器是否返回“填充正确”或“填充错误”的信息。这个“神谕”(Oracle)就是指服务器的这个响应行为
攻击者可以逐字节地解密密文。假设我们要解密密文分组 Cn:
- 构造密文:攻击者需要控制一个密文分组 Cn−1′(通常是伪造的)和一个目标密文分组 Cn
- 暴力破解:攻击者会尝试 Cn−1′ 的最后一个字节,从 0 到 255 遍历所有可能的值
- 发送给服务器:将伪造的
(IV + C_0 + ... + C_{n-2} + C_{n-1}' + C_n)
发送给服务器 - 观察响应:
- 如果服务器返回“填充正确”,说明填充字节的解密结果为
0x01
- 如果服务器返回“填充错误”,说明填充字节的解密结果不为
0x01
- 如果服务器返回“填充正确”,说明填充字节的解密结果为
- 推导:
- 当我们找到一个让服务器返回“填充正确”的 Cn−1′ 时,根据CBC模式的解密公式:
$P_n = D(C_n) \oplus C_{n-1}$
- 那么,伪造的密文解密后,其最后一个明文字节为
0x01
:$P_n'[last] = D(C_n)[last] \oplus C_{n-1}'[last] = 0x01$
- 我们可以推导出
D(C_n)[last]
的值:$D(C_n)[last] = P_n'[last] \oplus C_{n-1}'[last] = 0x01 \oplus C_{n-1}'[last]$
- 既然我们已经知道了 D(Cn) 的最后一个字节,我们就可以用同样的方法,依次解密倒数第二个字节、倒数第三个字节……
- 每解密一个字节,攻击者就构造一个新的 Cn−1′,使得它能让下一个填充字节的解密结果为
0x02
,然后继续这个过程,直到解密完整个分组
- 当我们找到一个让服务器返回“填充正确”的 Cn−1′ 时,根据CBC模式的解密公式: