CBC字节反转攻击详解 您所在的位置:网站首页 反转模式是什么 CBC字节反转攻击详解

CBC字节反转攻击详解

2023-11-17 03:00| 来源: 网络整理| 查看: 265

前言

CBC全称为密码分组链接模式。不同于ECB模式,在CBC模式中,每个明文块先与前一个密文块儿进行异或后,在进行加密。这种加密模式很好的隐藏了明文的统计特性,但是同样也暴露出了一个很严重的缺点。本文将针对CBC模式的特点,详细讲解字节反转攻击的原理及应用。 一、CBC加密模式

在这里插入图片描述

Plaintext:明文

IV:初始化向量

Ciphertext:加密后的数据

Key:密钥

加密过程转化成文字来叙述:

先将Plaintext分组(常见以16字节为一组)生成初始化向量IV和密钥Key(IV不需要保密,但一定要不可预测)将IV和明文1组异或将3中所得结果用Key进行加密,得到密文1组将密文1组当作新IV与明文2组进行异或处理将5中的结果用Key进行加密,得到密文2组重复上述步骤,最后将IV和所有的密文分组拼接起来,得到最终密文 二、CBC解密模式

在这里插入图片描述 ​ 解密过程转化成文字来叙述:

从密文中提取出IV,并将密文分组用Key将密文1组解密2中解密的结果与IV异或,获得明文1组密文1组成为新一轮的IV重复上述步骤,将所有明文分组拼接后,得到最终明文 三、CBC字节反转攻击原理

在这里插入图片描述

字节反转攻击原理文字描述:

​ 我们从上述图片可以看出,如果猜测出明文分组Pn,那么可以通过修改密文分组Ci-1为Ci-1 XOR Pn XOR A,那么解密出来的Pn的结果是A。当然我们一般是不可能直接猜出来整个明文分组Pn,我们更多遇到的是上述图片描述的那样,仅知道Pn中部分明文。同样地,我们依旧可以发动字节反转攻击,仅需要针对正确的位置进行修改密文内容即可。

​ 这种攻击的精髓在于:通过CBC的加密特点改变明文内容,但是这种改变并不会引起其它明文块儿对应位的改变。这种攻击常用来绕过过滤器,提权(比如从guest变为admin)等。

四、CBC字节反转攻击例题 from Crypto.Cipher import AES from Crypto.Random import get_random_bytes import base64 with open('./flag.txt','r') as f: FLAG = f.readline().strip() #print(FLAG) BLOCK_SIZE=16 IV = get_random_bytes(BLOCK_SIZE) key = get_random_bytes(BLOCK_SIZE) pad = lambda s: s + (BLOCK_SIZE - len(s) % BLOCK_SIZE) * chr(BLOCK_SIZE - len(s) % BLOCK_SIZE).encode() unpad = lambda s: s[:-ord(s[len(s) - 1:])] prefix = "flag="+FLAG+"&userdata=" suffix = "&user=guest" def menu(): print ("1. encrypt") print ("2. decrypt") return input("> ") def encrypt(): data = input("your data: ") plain = (prefix+data+suffix).encode() aes = AES.new(key, AES.MODE_CBC, IV) print (base64.b64encode(aes.encrypt(pad(plain)))) def decrypt(): data = input("input data: ").encode() aes = AES.new(key, AES.MODE_CBC, IV) plain = unpad(aes.decrypt(base64.b64decode(data))) #print (b'DEBUG ====> ' + plain) if plain[-5:]==b"admin": print (plain) else: print ("you are not admin") def main(): for i in range(10): cmd = menu() if cmd=="1": encrypt() elif cmd=="2": decrypt() else: exit() if __name__=="__main__": main() 例题分析:

​ 该题目希望我们提供一个加密的字符串,如果将该字符串解密所得最后几位内容为admin,那么将直接输出明文。由题目可得,明文由prefix+data+suffix三部分组成,其中flag藏在prefix中,data由用户输入,suffix隐匿着我们要修改的字段。明文分组长度是16字节,加密算法是AES,加密模式是CBC,填充方式是PKCS。

​ 根据CBC字节反转原理,解密Pn需要Cn-1的参与。那么在已知Pn部分明文是guest时,我们可在Cn-1中寻找确定相对的guest位置,然后对该位置的数值进行修改,譬如改为Ci-1[idx] XOR ord(‘g’) XOR ord(‘a’)。

我们的目标就是将guest修改为admin!

在这里插入图片描述

​ 我们可以先随便提供一个明文,然后将密文进行修改,使得解密后的字符串最后内容是admin,我们可以通过枚举flag的长度,从而确定需要在什么位置进行修改。

例题精讲: 步骤一:根据明文的形式,爆破flag的长度 pad = 16 data = 'a'*pad for x in range(10,100): BLOCK_SIZE = 16 prefix = 'flag='+'a'*x+"&userdata=" suffix = "&user=guest" plain = prefix + data + suffix 步骤二:确定guest的首字母的index idx = (22+x+pad) % BLOCK_SIZE + ((22+x+pad)//BLOCK_SIZE-1) * BLOCK_SIZE 步骤三:将Cn-1对应guest位置的数值进行修改 cipher[idx+0] = chr(ord(cipher[idx+0])^ord('g')^ord('a')) cipher[idx+1] = chr(ord(cipher[idx+1])^ord('u')^ord('d')) cipher[idx+2] = chr(ord(cipher[idx+2])^ord('e')^ord('m')) cipher[idx+3] = chr(ord(cipher[idx+3])^ord('s')^ord('i')) cipher[idx+4] = chr(ord(cipher[idx+4])^ord('t')^ord('n')) 完整exp(Python3版本)如下: from pwn import * import base64 import binascii context.log_level = 'debug' pad =16 data = b'a' * pad #r = remote("127.0.0.1",10050) for x in range(10,100): r = remote("127.0.0.1",10050) r.sendlineafter(b'> ', b'1') r.sendlineafter(b"your data:", data) #time.sleep(0.5) temp = r.recvline().decode()[2:] #print(temp) cipher =list(base64.b64decode(temp)) BLOCK_SIZE = 16 prefix = b'flag='+b'a'*x+b'&userdata=' suffix = b'&user=guest' plain = prefix + data + suffix idx = (22+x+pad)%BLOCK_SIZE + ((22+x+pad) // BLOCK_SIZE -1 ) * BLOCK_SIZE #print(idx) cipher[idx + 0] = cipher[idx + 0] ^ ord('g') ^ ord('a') cipher[idx + 1] = cipher[idx + 1] ^ ord('u') ^ ord('d') cipher[idx + 2] = cipher[idx + 2] ^ ord('e') ^ ord('m') cipher[idx + 3] = cipher[idx + 3] ^ ord('s') ^ ord('i') cipher[idx + 4] = cipher[idx + 4] ^ ord('t') ^ ord('n') #print(cipher) stemp = [binascii.unhexlify(hex(i)[2:].zfill(2).encode()) for i in cipher] stemp1 = b'' for i in stemp: stemp1 += i r.sendlineafter(b'> ',b'2') r.sendlineafter(b'input data: ', base64.b64encode(stemp1)) msg = r.recv().decode() #print(msg) #pause() if 'you are not admin' not in msg: print(msg) break r.close() 参考资料

https://ctf-wiki.github.io/ctf-wiki/crypto/blockcipher/mode/cbc-zh/#_7

https://maplege.github.io/2018/11/19/CBC-reverse/

https://quant67.com/post/crypt/cbc-crack/attack-on-cbc.html



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有