CBC 攻击
CBC加密过程
CBC工作于一个固定长度的比特组,将其称之为块。在本文中,我们将使用包含16字节的块。
CBC加密
如图:
加密
加密的过程
1、首先将明文分组(常见的以16字节为一组),位数不足的使用特殊字符填充。
2、生成一个随机的初始化向量(IV)和一个密钥。
3、将IV和第一组明文异或。
4、用密钥对3中xor后产生的密文加密。
5、用4中产生的密文对第二组明文进行xor操作。
6、用密钥对5中产生的密文加密。
7、重复4-7,到最后一组明文。
8、将IV和加密后的密文拼接在一起,得到最终的密文。
特点就是:前一块的密文用来产生后一块的密文[为了解决ECB模式的缺点]。
CBC解密
如图:
解密
解密过程
1、从密文中提取出IV,然后将密文分组。
2、使用密钥对第一组的密文解密,然后和IV进行xor得到明文。
3、使用密钥对第二组密文解密,然后和2中的密文xor得到明文。
4、重复2-3,直到最后一组密文。
CBC攻击(解密)
利用异或(xor)的特性,在CBC模式解密[也就是服务器解密验证]的时候进行攻击。如图:
攻击
通过修改密文的bit[这里毁损这一块密文,这个不重要],达到我们想要的目的明文。
比如账号是xdmin,通过CBC攻击,改成admin,提升权限.
作用:借由此可以绕过过滤器,或者改变用户权限提升至管理员
Ex
这里借助一道CTF题目来加深练习.
地址:https://github.com/pbiernat/BlackBox/tree/master/FL!P
搭建好题目,发现
1、题目采用AES_CBC模式
2、输入,以"getapikey:"+email.数据里不能有";"
def mkprofile(self, email):
if((";" in email)):
return -1
prefix = "comment1=wowsuch%20CBC;userdata="
suffix = ";coment2=%20suchsafe%20very%20encryptwowww"
ptxt = prefix + email + suffix
return encrypt_cbc(self.key, self.iv, ptxt)
#输入:
if(data.startswith("getapikey:")):
data = data[10:]
resp = self.mkprofile(data)
3、判断输入的字符是否含有";admin=true"字符串
def parse_profile(self, data):
ptxt = decrypt_cbc(self.key,self.iv, data.encode('hex'))
ptxt = ptxt.replace(" ","")
print ptxt
if ";admin=true" in ptxt:
return 1
return 0
分析
这里要求输入没有";", 判断必须有";"。 怎么办....
这里将ptxt提取出来进行分组[16]字节为一组,qadmin=truexxxxx是输入的数据,与生成的密文
comment1=wowsuch ------> 58bda6ae81ee242225740b1deb58c60f 1
%20CBC;userdata= ------> 44df15e1a75deb24f863bb3140cd3d3f 2
qadmin=truexxxxx ------> cd54766107c2104554d7a19d104ddfee 3
;coment2=%20such ------> f8c877b0349d39b5e0f1846599943ce7 4
......
这里关注将 qadmin=true ---> ;admin=true
cd54766107c2104554d7a19d104ddfee解密的第一位为X = Decode(cd54766107c2104554d7a19d104ddfee)[0]
其中q解密提取
q = 0x44 ^ X [0x44是上一步的密文,解密过程]
想将q变成";",这里就用上xor的特性。如果将0x44改成md ---> md = (0x44 ^ q ^ ;)
其中q解密提取
md ^ X = 0x44 ^ q ^ ; X =0x44 ^ X ^ q ^ ;= q ^ q ^ ;= ; (q^q=0)
这样就可以将q变成;
exp
#python3
import socket
import binascii
host = '172.10.22.70'
port = 9002
def Tostr(st):
return st.encode(encoding='UTF8')
def listTostr(data):
for i in range(len(data)):
n = hex(data[i])
if len(n)==4:
data[i] = str(hex(data[i])[2:])
else:
data[i] = '0'+str(hex(data[i])[2:])
return "".join(data)
def exp():
s = socket.socket()
s.connect((host,port))
s.recv(1024)
s.send(Tostr("getapikey:qadmin=truexxxxx"))
data = s.recv(1024)
data = binascii.unhexlify(data) #32->16byte
data = list(data)
data[16] = ord("q") ^ ord(";") ^ data[16] #第二个字符串加密后的第一位xor
data = listTostr(data)
s.send(Tostr("getflag:" + data))
data = (s.recv(1024)).decode('utf-8')
print(data)
if __name__ == '__main__':
exp()
网友评论