Padding oracle attack详细解析

AlexFrankly 2017-10-25 教学频道 0 0

*本文原创作者:flurry,本文属FreeBuf原创奖励计划,未经许可禁止转载

前言:

前段时间遇到一个挺有意思的题目,用到了padding oracle attack的相关知识,于是恶补了一下padding oracle attack相关内容,发现有许多需要知道的预备知识,了解很琐碎,本着取之于民用之于民同时也可以方便自己以后复习的心态,我决定整理一下这几天的所学所得,方便小白们一起学习(如果已经有一定基础只是对padding oracle attack本身感兴趣可以直接跳至第四部分)。

一、异或运算(XOR)

我们先首了解一下什么是异或运算。我们知道,计算机存储的数据是以二进制的格式存入的,把两段二进制数字进行异或运算的话,相同的得0,不同的得1,例如:

0101 XOR 0110 = 0011
65 XOR 42 = 107(十进制数先转为二进制再进行异或操作)

字符在计算机中有对应的ascii码值,对字符进行异或运算就是将两串字符对应的ascii码值相异或把得到的ascii码值对应的字符相异或,异或运算具有可逆性,如65 XOR 42 = 107 则 107 XOR 42 = 65,因此对于异或运算a XOR b = c,我们只需知道abc中的任意两个,将这两个相异或便可求出第三个,这个性质也是我们进行padding oracle attack的关键。

二、CBC模式

首先是CBC模式:CBC模式是一种分组链接模式,目的是为了使原本独立的分组密码加密过程形成迭代,使每次加密的结果影响到下一次加密。这可以强化加密算法的”敏感性”,即实现所谓的”雪崩效应”,在香浓理论中这就是”扰乱原则”(百度得到的定义不理解也不影响后面)。CBC是一种加密的模式,经常把DES或者AES算法(两种分组密码算法)作为加密使用的算法。这里先简单介绍一下分组加密,所谓分组加密顾名思义,就是按一定规则把明文分成一块一块的小组,DES分组长度是八字节而AES分组长度是十六字节,每组长度一致,加密时是按组进行加密的。CBC模式的加密过程如下图所示:

Padding oracle attack详细解析

图中的Plaintext就是按一定长度(长度取决于选用的加密算法)分好的待加密的明文组,Initialization Vector(IV值)是一个预设值,加密算法的密钥key也是设置好的。第一块明文和初始的IV值异或得到一个中间值,把这个中间值用CBC模式选用的加密方式(如AES)进行加密得到第一块密文,第二块明文和第一块密文异或得到中间值,对中间值加密得到第二块密文,以此类推第n块明文和第n-1块密文异或得到中间值然后再对中间值异或得到第n块密文,把这n块密文连在一起便得到了明文用CBC模式加密后的密文。

CBC模式解密过程是加密过程的逆过程,如下图所示:

Padding oracle attack详细解析

首先按照一定长度将密文分好组,其中密文的第一组是初始的IV值,第二组密文对应第一组明文。分好组后,从第二组密文开始依次用算法进行解密运算得到n组中间值,这时候得到的值并不是明文,要想得到明文还需进行一次异或操作,第一个中间值与初始IV值异或得到明文,第二个中间值与前一组的密文异或得到第二组明文,以此类推最后一组中间值与倒数第二组密文进行亦或便可得到最后一组明文,将所有的明文连在一起便是最终的明文。

 三、PKCS #5

既然CBC模式涉及到分组,那么就一定存在不能恰好被平均分组的情况,也就是说最后一组的长度可能不够长,这时候就需要对最后一组分组进行填充,使其和其他分组保持长度一致,这时候就需要了解一下填充所要遵循的规则了。对于采用DES算法进行加密的内容,填充规则遵循的是PKCS #5,而AES则是PKCS #7,实际上两者的要求基本一样,区别在于PKCS #5填充是八字节分组而PKCS #7是十六字节,换句话说就是填充的最大位数不一样,一个是0到8一个是0到16,下面我介绍一下PKCS #5的要求。为了保证每一组的长度一致,做法是在最后一个分组后填充一个固定的值,这个值的大小为填充的字节总数(十六进制表示)。例如最后还差4个字符,则填充四个0×04在最后,对于PKCS #5最多填充八位也就是八个0×08,所以填充字节的取值范围是0×01到0×08。需注意即便分组内容能正好平均分为n组,仍需要在最后一组后面填充一个八位分组,如下图所示:Padding oracle attack详细解析

以上,便是对PKCS #5的简要介绍,16字节的AES采用的是PKCS #7,只是分组长度不一样,也就是说填充字节的取值范围是0×00到0×10,填充的规则基本一样。

四、Padding oracle attack攻击原理:

接下来就是本文的重点了,前面说了那么多都是方便理解这一部分内容的理解。

Padding Oracle Attack是针对CBC链接模式的攻击,和具体的加密算法无关,换句话说,这种攻击方式不是对加密算法的攻击,而是针对算法的使用不当进行的攻击。那么padding oracle attack是怎么实现的呢?下面我将详细说一下我的理解。

首先我们了解一下使用CBC模式加密敏感信息的服务器是怎么处理我们提交的内容的。假设我们向服务器提交了正确的密码,我们的密码在经过CBC模式加密后传给了服务器,这时服务器会对我们传来的信息尝试解密,如果可以正常解密会返回一个值表示正确,如果不能正常解密则会返回一个值表示错误。而事实上,判断提交的密文能不能正常解密,第一步就是判断密文最后一组的填充值是否正确,也就是观察最后一组解密得到的结果的最后几位,如果错误将直接返回错误,如果正确,再将解密后的结果与服务器存储的结果比对,判断是不是正确的用户。也就是说服务器一共可能有三种判断结果:

1.密文不能正常解密;

2.密文可以正常解密但解密结果不对;

3.密文可以正常解密并且解密结果比对正确;

其中第一种情况与第二 三种情况的返回值一定不一样,这就给了我们可乘之机——我们可以利用服务器的返回值判断我们提交的内容能不能正常解密,进一步讲,我们可以知道最后一组密文的填充位符不符合填充标准。

Padding oracle attack详细解析

如上图所示,明文填充了四位时,如果最后一组密文解密后的结果(Intermediary Value也就是中间值)与前一组密文(Initialization Vector也就是IV值)异或得到的最后四位是0×04,那么服务器就会返回可以正常解密。

回忆一下前面我们说过的CBC模式的解密过程,第n组密文解密后的中间值与前一组的密文异或便可得到明文,现在我们不知道解密的密钥key,但我们知道所有的密文,因此只要我们能够得到中间值便可以得到正确的密文(进行一次异或运算便可),而中间值是由服务器解密得到的,因此我们虽然不知道怎么解密但我们可以利用服务器帮我们解密,我们所要做的是能确定我们得到的中间值是正确的,这也是padding oracle attack的核心——找出正确的中间值。

那么我们该如何利用服务器帮我们找到中间值呢?我们刚刚说过,服务器会根据我们提交的密文能否正确解密给我们返回不同的值,这里就有一个可以利用的逻辑判断,判断的标准是最后几位的填充值是否符合标准,再回忆一下前面说的PKCS #5填充和CBC模式的解密过程,我们不难理解下面的攻击过程:

(1)假设我们捕获到了传输的密文并且我们知道是CBC模式采用的什么加密算法,我们把密文按照加密算法的要求分好组,然后对倒数第二组密文进行构造;

(2)先假定明文只填充了一字节,对倒数第二组密文的最后一字节从0×00到0xff逐个赋值并逐个向服务器提交,直到服务返回值表示构造后的密文可以正常解密,这意味着构造后的密文作为中间值(图中黄色的那一行)解密最后一组明文,明文的最后一位是0×01(如图所示),也就是说构造的倒数第二组密文的最后一字节与最后一组密文对应中间值(绿色的那一行)的最后一位相异或的结果是0×01;

Padding oracle attack详细解析

(3)利用异或运算的性质,我们把我们构造的密文的最后一字节与0×01异或便可得到最后一位密文解密后的中间值是什么,这里我们设为M1,这一过程其实就是对应下图CBC解密过程中红圈圈出来的地方,1就是我们想要得到的中间值,二就是我们构造的密文也就是最后一组密文的IV值,我们已经知道了plaintext的最后一字节是0×01,从图中可以看到它是由我们构造的IV值与中间值的最后一字节异或得到的;

Padding oracle attack详细解析

(4)再假定明文填充了两字节也就是明文最后两字节是0×02,接着构造倒数第二组密文,我们把M1与0×02异或可以得到填充两字节时密文的最后一位应该是什么,这时候我们只需要对倒数第二位进行不断地赋值尝试(也是从0×00到0xff),当服务器返回值表示可以正常解密时,我们把此时的倒数第二位密文的取值与0×02异或便可得到最后一组密文倒数第二字节对应的中间值;

(5)后再构造出倒数第三倒数第四直到得到最后一组密文的中间值,把这个中间值与截获的密文的倒数第二位异或便可得到最后一组分组的明文;

(6)舍弃掉最后一组密文,只提交第一组到倒数第二组密文,通过构造倒数第三组密文得到倒数第二组密文的铭文,最后我们便可以得到全部的明文

五、总结

Padding oracle attack的关键思路就在于通过构造IV值(也就是前一组密文)利用服务器的返回值结合PKCS #5来找到正确的中间值,从而绕过加密算法,直接得到解密后的内容。

其实就是通过服务器的返回值判断自己构建的IV值对不对,进而猜测出正确的中间值Intermediary Value,中间值再和获取到的原本的IV值异或便可得到明文,因此攻击成立的两个重要假设前提:

(1)  攻击者能够获得密文(Ciphertext),以及附带在密文前面的IV(初始化向量)

(2)  攻击者能够触发密文的解密过程,且能够知道密文的解密结果

能够获得密文我们才能得到正确的明文,而密文的第一组分组需要有正确的初始化向量才能解密。能触发密文的解密过程才能在不知道密钥的情况下绕过加密算法直接得到我们需要的结果,而知道密文的解密结果是通过服务器返回值来判断结果是不是符合填充标准来实现的,例如符合填充一位的话解密结果就是0×01,而我们正是通过把自己构造的IV值与解密结果异或才得到正确的中间值进而得到明文的。

*本文原创作者:flurry,本文属FreeBuf原创奖励计划,未经许可禁止转载

转载请注明来自华盟网,本文标题:《Padding oracle attack详细解析》

喜欢 (0) 发布评论