Sky's blog

padding oracle和cbc翻转攻击

Word count: 1,356 / Reading time: 5 min
2017/12/13 Share

知识介绍

CBC加密模式:

CBC解密模式:

Padding Oracle Attack攻击过程

这里主要关注一下解密过程
密文cipher首先进行一系列处理,如图中的Block Cipher Decryption
我们将处理后的值称为middle中间值
然后middle与我们输入的iv进行异或操作
得到的即为明文
但这里有一个规则叫做Padding填充:
因为加密是按照16位一组分组进行的
而如果不足16位,就需要进行填充

比如我们的明文为admin
则需要被填充为 admin\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b
一共11个\x0b
如果我们输入一个错误的iv,依旧是可以解密的,但是middle和我们输入的iv经过异或后得到的填充值可能出现错误
比如本来应该是admin\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b
而我们错误的得到admin\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x3b\x2c
这样解密程序往往会抛出异常(Padding Error)
应用在web里的时候,往往是302或是500报错
而正常解密的时候是200
所以这时,我们可以根据服务器的反应来判断我们输入的iv
我们假设middle中间值为(为了方便,这里按8位分组来阐述)

1
0x39 0x73 0x23 0x22 0x07 0x6a 0x26 0x3d

正确的解密iv应该为

1
0x6d 0x36 0x70 0x76 0x03 0x6e 0x22 0x39

解密后正确的明文为:

1
T E S T 0x04 0x04 0x04 0x04

但是关键点在于,我们可以知道iv的值,却不能得到中间值和解密后明文的值
而我们的目标是只根据我们输入的iv值和服务器的状态去判断出解密后明文的值
这里的攻击即叫做Padding Oracle Attack攻击
这时候我们选择进行爆破攻击
首先输入iv

1
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00

这时候和中间值middle进行异或得到:

1
0x39 0x73 0x23 0x22 0x07 0x6a 0x26 0x3d

而此时程序会校验最后一位padding字节是否正确
我们知道正确的padding的值应该只有0x01~0x08,这里是0x3d,显然是错误的
所以程序会抛出500
知道这一点后,我们可以通过遍历最后一位iv,从而使这个iv和middle值异或后的最后一位是我们需要0x01
这时候有256种可能,不难遍历出
Iv:

1
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x3c

Middle:

1
0x39 0x73 0x23 0x22 0x07 0x6a 0x26 0x3d

两者异或后得到的是:

1
0x39 0x73 0x23 0x22 0x07 0x6a 0x26 0x01

这时候程序校验最后一位,发现是0x01,即可通过校验,服务器返回200
我们根据这个200就可以判断出,这个iv正确了
然后我们有公式:

1
2
Middle[8]^原来的iv[8] = plain[8]
Middle[8]^现在的iv[8] = 0x01

故此,我们可以算出middle[8] = 0x01^现在的iv[8]
然后带入式1:

1
Plain[8] = 0x01^现在的iv[8]^原来的iv

即可获取明文plain[8]= 0x01^0x3c^0x39=0x04
和我们之前解密成功的明文一致(最后4位为填充)
下面我们需要获取plain[7]
方法还是如出一辙
但是这里需要将iv更新,因为这次我们需要的是2个0x02,而非之前的一个0x01
所以我们需要将现在的iv[8] = middle[8]^0x02

为什么是现在iv[8] = middle[8]^0x02
因为现在的iv[8]^middle[8]=服务器校验的值
而我们遍历倒数第二位,应该是2个0x02,所以服务器希望得到的是0x02,所以

1
2
现在的iv[8]^middle[8]=0x02
故此iv[8] = middle[8]^0x02


然后再继续遍历现在的iv[7]
方法还是和上面一样,遍历后可以得到
Iv:

1
0x00 0x00 0x00 0x00 0x00 0x00 0x24 0x3f

Middle:

1
0x39 0x73 0x23 0x22 0x07 0x6a 0x26 0x3d

两者异或后得到的是:

1
0x39 0x73 0x23 0x22 0x07 0x6a 0x02 0x02

然后此时的明文值:

1
Plain[7]=现在的iv[7]^原来的iv[7]^0x02

所以Plain[7] = 0x02^0x24^0x22=0x04
和我们之前解密成功的明文一致(最后4位为填充)
最后遍历循环,即可得到完整的plain

CBC翻转攻击过程

这个实际上和padding oracle攻击差不多

还是关注这个解密过程
但这时,我们是已知明文,想利用iv去改变解密后的明文
比如我们知道明文解密后是1dmin
我们想构造一个iv,让他解密后变成admin
还是原来的思路

1
原来的Iv[1]^middle[1]=plain[1]

而此时
我们想要

1
构造的iv[1]^mddle[1]=’a’

所以我们可以得到

1
构造的iv[1] = middle[1]^’a’


1
middle[1]=原来的iv[1]^plain[1]

所以最后可以得到公式

1
构造的iv[1]= 原来的iv[1]^plain[1]^’a’

所以即可造成数据的伪造
我们可以用这个式子,遍历明文,构造出iv,让程序解密出我们想要的明文
题目题解:
有了上面的知识基础,我们就可以很快速的破解这道题
首先是我们未知Plain,即这里的global $id
所以可以利用padding oracle攻击去得到这个值plain
然后得到这个值后,再利用cbc翻转攻击,将这个plain伪造成我们需要的admin

CATALOG
  1. 1. 知识介绍
    1. 1.1. Padding Oracle Attack攻击过程
    2. 1.2. CBC翻转攻击过程