CBC 字节翻转攻击

Author Avatar
Tr0y 10月 12, 2017 23:05:09 本文共 959 字
  • 文为知己者书
  • 在其它设备中阅读本文章

CBC 字节翻转攻击的记录

原理

CBC 模式就不多说了,只放解密过程
attack.jpg
可以看到,当修改前一个 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 个字节的块:

  1. Block 1:a:2:{s:4:"name";
  2. Block 2:s:6:"sdsdsd";s:8
  3. Block 3::"greeting";s:20
  4. Block 4::"echo 'Hello sd
  5. 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 是攻击脚本

# -*- coding: cp936 -*-
from Server import *
from re import findall
from Crypto.Util import strxor

# 将位于第 Block 个块中第 loc 个字符修改为 char
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 '  [-]' + m

print '[+]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 '  [-]' + c

print '[!]All Done!'


模拟服务端

Server.py 对传入的 M 进行加密,使用随机的 Key 以及 IV,并返回解密的密文

# -*- coding: cp936 -*-
from Crypto.Cipher import AES
from Crypto import Random
import random
import 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

结果

[!]将 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!

End

What do you think?

本文标题: CBC 字节翻转攻击
原始链接: http://www.tr0y.wang/2017/10/12/CBCByteFlippingAttack/
发布时间: 2017.10.12-23:05
最后更新: 2018.11.03-20:29
版权声明: 本站文章均采用CC BY-NC-SA 4.0协议进行许可。转载请注明出处!