CBC字节翻转攻击
参考文章
CBC翻转攻击方法的精髓在于:
通过损坏密文字节来改变明文字节。(注:借助CBC内部的模式)借由此可以绕过过滤器,或者改变用户权限提升至管理员,又或者改变应用程序预期明文以尽猥琐之事。
整个加密的过程简单说来就是:
- 首先将明文分组(常见的以16字节为一组),位数不足的使用特殊字符填充。
- 生成一个随机的初始化向量(IV)和一个密钥。
- 将IV和第一组明文异或。
- 用密钥对3中xor后产生的密文加密。
- 用4中产生的密文对第二组明文进行xor操作。
- 用密钥对5中产生的密文加密。
- 重复4-7,到最后一组明文。
- 将IV和加密后的密文拼接在一起,得到最终的密文。
解密的过程其实只要理解了加密,反过来看解密过程就也很简单了,同样的,前一块密文参与下一块密文的还原。
- 从密文中提取出IV,然后将密文分组。
- 使用密钥对第一组的密文解密,然后和IV进行xor得到明文。
- 使用密钥对第二组密文解密,然后和2中的密文xor得到明文。
- 重复2-3,直到最后一组密文。
具体加密解密过程这里不过多叙述,请参考开始提到的文章.
首先得到一个登陆界面,随意输入登陆,提示需要admin才能看到flag.
username=zdmin&password=12345
登陆之后得到第一次的cookie
iv=uL86lH%2BXnh%2BUBpm6ZdAzeg%3D%3D
cipher=VnxHhOF%2Fxnne4kBWpJWw8uRj2oW6qRdShJRFbwsLRkuwTDxwI%2BzTD8OC9b1%2F8TWv9F%2FuicGOxNJn3SWqOGLewQ%3D%3D
编写脚本将cipher替换
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import base64
import requests
import urllib
iv_raw='uL86lH%2BXnh%2BUBpm6ZdAzeg%3D%3D' #这里填写第一次返回的iv值
cipher_raw='VnxHhOF%2Fxnne4kBWpJWw8uRj2oW6qRdShJRFbwsLRkuwTDxwI%2BzTD8OC9b1%2F8TWv9F%2FuicGOxNJn3SWqOGLewQ%3D%3D' #这里填写第一次返回的cipher值
#print "iv_raw: " + iv_raw
#print "cipher_raw: " + cipher_raw
cipher = base64.b64decode(urllib.unquote(cipher_raw))
#s:2:{s:8:"username";s:5:"zdmin";s:8:"password";s:5:"12345"}
#s:2:{s:8:"userna
#me";s:5:"zdmin";
#s:8:"password";s
#:3:"12345";}
xor_cipher = cipher[0:9] + chr(ord(cipher[9]) ^ ord('z') ^ ord('a')) + cipher[10:] #请根据你的输入自行更改,原理看上面的介绍
xor_cipher=urllib.quote(base64.b64encode(xor_cipher))
print "cipher:" + xor_cipher
将得到的翻转之后的cipher上传
这里注意要将提交的数据删除,不然将造成重新获得cookie,触发不了现象.
得到网站返回
base64_decode('CgyrbtJF60ZGs6qgRn6AhW1lIjtzOjU6ImFkbWluIjtzOjg6InBhc3N3b3JkIjtzOjU6IjEyMzQ1Ijt9') can't unserialize
再次编写脚本
将无法反序列化的字符串赋给cipher
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import base64
import requests
import urllib
cipher = 'CgyrbtJF60ZGs6qgRn6AhW1lIjtzOjU6ImFkbWluIjtzOjg6InBhc3N3b3JkIjtzOjU6IjEyMzQ1Ijt9'#填写提交后所得的无法反序列化密文
iv = 'uL86lH%2BXnh%2BUBpm6ZdAzeg%3D%3D'#一开始提交的iv
#cipher = urllib.unquote(cipher)
cipher = base64.b64decode(cipher)
iv = base64.b64decode(urllib.unquote(iv))
newIv = ''
right = 'a:2:{s:8:"userna'#被损坏前正确的明文
for i in range(16):
newIv += chr(ord(right[i])^ord(iv[i])^ord(cipher[i])) #这一步相当于把原来iv中不匹配的部分修改过来
print urllib.quote(base64.b64encode(newIv))
最后将得到的newiv
赋给iv
,cipher依然是翻转之后得到的.
上传得到flag.
还不快抢沙发