CBC 字节翻转攻击
CBC 字节翻转攻击的记录
原理
CBC 模式就不多说了,只放解密过程
可以看到,当修改前一个 Block1 时,会影响下一个 Block2 的解密,因为前一个 Block1 是作为后一块 Block2 的 IV 的
这就是字节翻转攻击开始发挥作用的地方
如果我们改变 Block1 的一个字节,然后与下一个解密后的组块 Block2 异或,我们就可以得到一个不同的明文了
栗子
M = a:2:{s:4:"name";s:6:"sdsdsd ";s:8:"greeting";s:20:"echo 'Hello sdsdsd!'";}
我们的目标是将 s:6
当中的数字 6 转换成数字 0。我们需要做的第一件事就是把明文分成 16 个字节的块:
Block 1:a:2:{s:4:"name";
Block 2:s:6:"sdsdsd";s:8
Block 3::"greeting";s:20
Block 4::"echo 'Hello sd
Block 5:sdsd!'";}
我们的目标字符位于块 2,这意味着我们需要改变块 1 的密文来改变第二块的明文。
知道改哪了,那么要改成啥呢?
设图中第一个红块为 C1,它对应的明文块为 M1
第二个红块为 M2,它经过加密函数后的值记为 I(还没经过异或的值),它对应的密文块为 C2
根据这个流程,可知:
C1 ^ I = M2
对应上面的那个例子,就是
C1 为'2'对应的密文
I 为'6'经过加密函数后的值
M2 即为'6'
我们要求 C1'的值,根据异或特性,有
C1' = M2' ^ I = M2' ^ C1 ^ M2
要想使'6'成为我们想要得到的值,C1' 就要满足上述条件
代码
Attack
Attack.py 是攻击脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
from Server import *from re import findallfrom Crypto.Util import strxor Block = 1 loc = 7 char = '0' rawM = '''a:2:{s:4:"name";s:6:"sdsdsd";s:8:"greeting";s:20:"echo 'Hello sdsdsd!'";}''' print '[!]将 rawM 中的 s:4:"name"; 改为 s:0:"name";' Blockn, b = divmod (len (rawM), 16 )if b: Blockn = Blockn + 1 rawM = rawM[::-1 ].zfill(Blockn * 16 )[::-1 ] C = CreateC(rawM)print '[+]The rawM is:' splitM = findall('.{16}' , rawM)for m in splitM: print ' [-]' + mprint '[+]The rawC is:' splitC = findall('.{32}' , C)for c in splitC: print ' [-]' + c changeBlock = findall('.{2}' , splitC[Block - 1 ])print '[!]Block' , Block - 1 , 'loc' , loc, 'char had changed from' , changeBlock[loc], 'to' , changeBlock[loc] = hex (int (changeBlock[loc], 16 ) ^ ord (rawM[(Block-1 ) * 16 + loc]) ^ ord (char))[2 :].zfill(2 )print changeBlock[loc] splitC[Block-1 ] = '' .join(changeBlock) modifyC = '' .join(splitC)print '[+]The attackedC is:' for c in findall('.{32}' , modifyC): print ' [-]' + c CheckM = Check(modifyC.decode('hex' ))print '[+]The attacked M is:' for c in findall('.{16}' , CheckM[16 :]): print ' [-]' + cprint '[!]All Done!'
模拟服务端
Server.py 对传入的 M 进行加密,使用随机的 Key 以及 IV,并返回解密的密文
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
from Crypto.Cipher import AESfrom Crypto import Randomimport randomimport string cipher = None def CreateC (M ): '''使用随机的 key 与 iv 加密明文,返回密文''' global cipher K = list (string.ascii_letters + string.digits) iv = K[:] random.shuffle(K) iv = Random.new().read(AES.block_size) cipher = AES.new('' .join(K[:32 ]), AES.MODE_CBC, iv) return iv.encode('hex' )+cipher.encrypt(M).encode('hex' )def Check (C ): '''检查 CBC 字节翻转攻击是否成功''' global cipher M = cipher.decrypt(C) return M
结果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
将 rawM 中的 s:4:"name" ; 改为 s:0:"name" ; The rawM is : a:2:{s:4:"name" ; s:6:"sdsdsd" ;s:8 :"greeting" ;s:20 :"echo 'Hello sd [-] sdsd!'" ;}0000000 The rawC is : bcb20b483bfb9d718ec95a35b2d5ca4d 88a9e8623ea4f5d920313dda254316d5 aed2b33aeada7885f64302a9c1dc2975 df9a6c328d837d1169a34e71d4d0344b 86fcf2c5f11135aa218b3d52958daa41 b38ab120da3bd7d301580bafcd3f1ab5 Block 0 loc 7 char had changed from 71 to 75 The attackedC is : bcb20b483bfb9d758ec95a35b2d5ca4d 88a9e8623ea4f5d920313dda254316d5 aed2b33aeada7885f64302a9c1dc2975 df9a6c328d837d1169a34e71d4d0344b 86fcf2c5f11135aa218b3d52958daa41 b38ab120da3bd7d301580bafcd3f1ab5 The attacked M is : a:2:{s:0:"name" ; s:6:"sdsdsd" ;s:8 :"greeting" ;s:20 :"echo 'Hello sd [-] sdsd!'" ;}0000000 All Done!
- By:tr0y.wang
评论