CBC字节翻转攻击

前段时间ISCC遇到了一道CBC字节翻转攻击的题目,感觉比较有意思,就总结了一下。

1、首先来了解一下CBC模式:CBC模式是分组密码模式的一种,其加密过程如下:
这里写图片描述
IV:初始化向量。
plaintext:明文分组。
cipertext:密文分组。
key:密钥。
CBC工作于一个固定的比特组,称为一个块。本文我们把16字节作为一个块。
简单来说:CBC模式加密就是先将明文进行分组(常见16字节为一组),将每个明文分组与前一个密文分组进行XOR运算再通过key加密得到密文,其中第一组明文与初始化向量IV进行XOR运算得到第一组密文。
最后将IV与得到的密文拼接得到最终的密文。
从加密的方式我们不难发现各组都是有关联的,这是与ECB得不同之处,与ECB比较相对比较安全。
其解密过程:
这里写图片描述
理解了加密,解密也容易理解,就是加密得逆过程:从密文中提取出IV,然后分组,每组密文先用key解密,然后再与上一组得密文XOR运算得到明文,其中第一组用key解密之后再和IV XOR运算得到明文。

2、从CBC模式得原理我们不难发现 如果我们想改变解密后的某一明文,得到我们想得到得明文,如果是第一组,只需要改变IV,否则只需要改变上一组密文,就可以控制我们得到的明文。
如下图:
这里写图片描述
我们要改变1处想要得到特定明文,就可以修改2处的密文,这就是CBC字节翻转攻击的简单理解。
3、利用CBC字节翻转攻击的题目往往是修改密文,使密文修改后解密得到我们想得到的明文,绕过限制。
这类题目的源码都是差不多的,以下面源码为例分析一下:
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
源码的意思是,随机产生初始化向量IV
把输入的username序列化 然后加密 IV也加密
解密并验证 如果username为admin 则输出flag
但是后边限制了post的username 不能为admin
我们便可以用CBC字节翻转攻击绕过这种限制,也就是修改加密后username 使其解密后为admin 得到flag。
3、例题:(ISCC2018. Only admin can see flag)

根据提示在index.txt 看到源码:
这里写图片描述
这里写图片描述
审计代码,发现admin登陆才可以得到flag,但是又限制post的username不能为admin,很显然要用CBC字节翻转攻击,先用abmin 登陆,再根据攻击原理改为admin。

用username=abmin 登陆,bp抓包:
这里写图片描述
得到IV 和cipher。

根据CBC加密过程我们先将输入序列化并分组(16字节为一组):
s:2:{s:8:”username”;s:5:”abmin”;s:8:”password”;s:5:”abmin”;}
① s:2:{s:8:”userna
② me”;s:5:”abmin”;
③ s:8:”password”;s
④ :5:”abmin”;}
分析:我们的目是把abmin 改为admin 由分组可知b在第二组的第11位,所以我们要修改第一组的u 脚本实现:

1
2
3
4
5
6
7
import base64
nweCipher=''

cipher = 'bp抓到的cipher经过url解密后的值'
cipher = base64.b64decode(cipher) #先进行解密
newCipher = cipher[0:11] + chr(ord(cipher[11])^ord('b')^ord('d')) + cipher[12:] #XOR运算修改
print base64.b64encode(newCipher) #再进行加密

这里写图片描述

在bp中添加cookie IV和修改后的cipher(脚本后得到的经过url加密) 注意添加前把post清空 然后go
这里写图片描述
返回结果:
这里写图片描述
回应无法反序列化,把无法反序列化字符串解密,发现已经变成了admin,但是我们翻转的时候破坏了第一组,所以无法反序列化,那我们需要把IV修复。

1
2
3
4
5
6
7
8
9
10
11
12
import base64
import urllib
cipher = ''#无法反序列化的字符串
iv = ''#先前得到的IV

cipher = base64.b64decode(urllib.unquote(cipher))#给cipher解密
iv = base64.b64decode(iv) #给先前的IV解密
newIv = ''
right = ''#破坏前正确的字符串
for i in range(16):
newIv += chr(ord(right[i])^ord(iv[i])^ord(cipher[i]))#一位位修复
print urllib.quote(base64.b64encode(newIv))

返回:
这里写图片描述
再cookie添加 生成的IV 和 修改的cipher 即可得到flag。
这里写图片描述

-------------本文结束有错指正哦!-------------