(一)PaddingOracle Attack
Padding OracleAttack是在Eurocrypt2002大会上,Vaudenay所介绍的一种针对CBC模式的攻击方法。它可以在不知道密钥的情况下,通过对paddingbytes的尝试,获取加密过程中的IntermediaryValue,从而还原明文或构造出任意明文的密文。
(二)加解密原理
分组加密算法在实现加解密时,需要把消息进行分组,分组(block)的大小一般有64bit,128bit,256bit等。
本文以CBC模式为例,对攻击原理进行简单的阐述。
图一:CBC加密模式
我们以8个字节一个block为例,首先将第一组的明文与初始iv进行异或之后进行相应的加密算法运算。计算完第一组后,将第一组获得的密文作为第二组的iv进行运算,如此类推,得到所有明文加密的结果。
如果在这个加密的过程中,最后一个分组的消息长度(明文长度)没有达到block的大小,则需要对其填充一些字节(padding)。
图二 padding标准PKCS5
上图padding例子使用现行最常见的padding标准PKCS#5。当需要填充1个字节时,填充值为0x01;当需要填充2个字节时,其填充值为0x02,0x02;当需要填充3个字节时,其填充值为0x03,0x03,0x03……
图三 CBC解密方式
类似的,解密过程与加密过程类似。首先将第一分组的密文进行解密运算,之后与初始iv进行异或,得出对应的明文。计算完第一分组后,将第一分组的密文作为第二分组的iv参与运算,如此类推得到所有分组密文的解密结果。
加解密原理大致阐述了一下,读者还记得上面提到的PaddingOracleAttack的特点吗?即在不知道密钥的情况下,还原明文或构造出任意明文的密文。所以下面请将注意力转移到解密部分,我们来仔细分析解密部分的一些特点,想办法做出PaddingOracle Attack的功能。
(三)攻击原理
在密钥一定的情况下,对密文进行解密算法运算,我们是可以得出一个与明文唯一对应的密文。在上文所说的解密过程中,进行解密算法运算只是每一组运算中的一个步骤,接下来是另一个步骤,即异或出结果。在这个过程中,使用解密算法运算得出的密文我们将其称为Intermediary Value。
小结一:每组密文解密所得到的IntermediaryValue都是固定的(因为与明文唯一对应),而我们暂时不知道它的值(因为我们不知道密钥)
接下来我们来分析异或部分
图四 CBC解密细节
可以看到,IntermediaryValue ⊕ iv = 明文。
请再次仔细想一想,在不知道密钥的情况下,还原明文或构造出任意明文的密文。所以,我们可以认为明文已知。
又因为Intermediary虽然未知,但是它的值是固定的,因此我们可以将上面这个表达式转换为
明文 =Intermediary Value ⊕ iv
所以,我们慢慢调整iv的值,以期得到与我们想要的明文一致的iv值,并一个字节一个字节的尝试,直到得出分组所使用的iv值。(iv每一个字节从0x00到0xFF进行尝试)
小结二:通过上面的推断,我们已经获取到了iv和明文值
继续看这个公式明文 = Intermediary Value ⊕ iv
我们继续做一下转换 Intermediary Value = 明文⊕ iv
因为明文和iv都已知了,因此我们可以通过异或得到IntermediaryValue的值。IntermediaryValue已知,那么我们就可以通过IntermediaryValue ⊕ 我们想要的明文=> 得到对应的iv
推导出最后一个分组使用的iv后,将此iv作为第一个分组的密文,再次进行推导,以此类推,便可以找到解密为任意明文的密文和iv对了
总结:明文 =Intermediary Value ⊕ iv
通过推导,我们可以得到解密为任意明文的密文和iv对,达成了既定目标。这里值得注意的是,需要对密文进行解密才能得出对应的IntermediaryValue,因此如果我们在没有密钥的情况下,需要通过一定的办法,触发app的解密程序,获取IntermediaryValue,从而继续我们上面对iv的推导。
(一)题目来源
常见的一道基础CBC翻转字节攻击
(二)题目关键代码(伪代码)
做题步骤
* 1.源码泄露
* 2.代码审计
题目核心逻辑伪代码如下图所示
图五 题目核心逻辑伪代码
所以我们可以知道,考点在于使用服务器为用户设置的密文和iv,进行某些操作,使得密文解密后的用户名为admin
(三)解题方法
1.利用网上到处都是的CBC翻转字节攻击代码进行
2.利用《白帽子讲web安全》内的PaddingOracle Attack的示例代码进行攻击(修改过的脚本代码附后)
我们在这里使用第二种方法进行,由于存在源码泄露,我在源码中找到了加密密钥,因此我不需要对触发app的解密代码来获取IntermediaryValue。可以直接使用密钥进行解密运算,从而获取解题所需的密文和iv对。
图六 攻击脚本运行结果
获取到密文和iv对之后,我们替换掉原先设置的密文和iv对,即可getflag。
图七 getflag截图
(四)章节小结
实际上这里取巧了,获得了题目加密的密钥。如果题目不能获取到密钥的话(实际攻击场景中常见),需要对脚本进行一些修改,触发攻击对象的解密程序,获取IntermediaryValue。
实际上写下这篇博文也是因为这个思考,最近所在的实验室办校内ctf比赛。作为客服的我无聊看了一下web题,又无意中突然发现题目的密钥长度没有达到算法预期,不禁产生了疑问。所以下面部分是对PHP的openssl_encrypt/openssl_decrypt中对key处理的研究
(一)问题来源
图八 问题来源
(二)源码跟进分析
图九 openssl_encrypt()源代码
可以看到,我们在使用openssl_encrypt函数时,输入的key(密钥)即是图中的参数password,而在第6624行中,密钥作为形参传到了一个名为"php_openssl_cipher_init"的函数中,我们继续跟进。
图十php_openssl_cipher_init( )源码
可以看到在函数中的第6511和第6512两行中,分别获取了用户输入的密钥长度和加密算法对应的规定密钥长度,显然,我们想要找到处理就在这个地方,继续往下看。
图十一 密钥处理部分分析
图片上我加了注释,解释应该十分清晰了。
(三)脚本修改
图十二 脚本修改
根据上面得出的处理结果,对攻击脚本进行修改(主要增加密钥处理功能)
相关操作学习:密码学原理:http://www.hetianlab.com/cour.do?w=1&c=c990c65e-108f-4d10-9efa-4aad77fc852b
本文脚本源码:https://github.com/Porlockzzz/attackScript/blob/master/padding_oracle_attack.py