SQLMAP 流程分析

2019-03-19  本文已影响0人  Franchen

SQLMAP运行流程

0x00 CheckWAF

通过插入一个触发WAF的payload,判断插入前后请求内容的相似度,如果小于某个阈值则认为存在WAF,将提示使用tamper进行绕过。

如何选用tamper:先手工注入关键词,判断是否被过滤。比如空格、等号、select等,再选用相应的tamper。

如何绕过union+select,可以考虑一下几种形式:

然后自己写tamper


0x01 checkStability

检查原始页面是否存在动态内容


0x02 参数预处理和动态参数检查


0x03 启发式 sql 注入判断

启发式 sql 注入检测整体逻辑

前提:没有开启 nullConnection 并且页面并不是 heavilyDynamic,否则将无法根据返回内容判断是否可能存在注入点。

决策:决定注入的结果报告的,主要在于两个标识位,分别为:casting 与 result。


0x04 SQL注入检查(checkSqlInjection)

sqlmap 中最核心的函数,大致执行步骤分为如下几个大部分:

  1. 根据已知参数类型,筛选 Boundary边界模型

边界主要取决于当前“拼接”的 SQL 语句的上下文,常见上下文:

  1. 当未指定数据库类型时,启发式检测数据库类型(heuristicCheckDbms)

检测核心原理:利用简单的布尔盲注构造(SELECT '[RANDSTR]' [FROM_DUMMY_TABLE.get(dbms)] )='[RANDSTR1]'

FROM_DUMMY_TABLE = {
    DBMS.ORACLE: " FROM DUAL",
    DBMS.ACCESS: " FROM MSysAccessObjects",
    DBMS.FIREBIRD: " FROM RDB$DATABASE",
    DBMS.MAXDB: " FROM VERSIONS",
    DBMS.DB2: " FROM SYSIBM.SYSDUMMY1",
    DBMS.HSQLDB: " FROM INFORMATION_SCHEMA.SYSTEM_USERS",
    DBMS.INFORMIX: " FROM SYSMASTER:SYSDUAL"
}

例如,检查是否是 ORACLE 的时候,就会生成 (SELECT 'abc' FROM DUAL)='abc'(SELECT 'abc' FROM DUAL)='abcd',如果返回结果不一致,则表明数据库就是 ORACLE。

  1. payload 预处理

测试数据模型中读取的Payload,都需要经过一些随机化和预处理,形成<payload><comment>,涉及:

  1. 过滤与排除不合适的测试用例。
  1. 将筛选出的边界与预处理后的 payload 整合

最终变成<prefix> <payload><comment> <suffix>的结构。

  1. payload 渲染。
  1. 针对四种类型的注入分别进行 response 的响应和处理。
  1. 得出结果,返回结果。

0x05 布尔盲注分析

# 分析案例
<test>
    <title>PostgreSQL OR boolean-based blind - WHERE or HAVING clause (CAST)</title>
    <stype>1</stype>     # 布尔注入
    <level>3</level>     # 一般的测试,约200-500请求
    <risk>3</risk>       # 对数据库危害较大,可以插入、修改、删除数据。
    <clause>1</clause>   # 适用于WHERE / HAVING语句
    <where>2</where>     # 将原参数替换成一个随机的负数,然后再添加到后面。如 id=[-RANDNUM]<prefix> <payload><comment> <suffix>
    <vector>OR (SELECT (CASE WHEN ([INFERENCE]) THEN NULL ELSE CAST('[RANDSTR]' AS NUMERIC) END)) IS NULL</vector>
    <request>
        <payload>OR (SELECT (CASE WHEN ([RANDNUM]=[RANDNUM]) THEN NULL ELSE CAST('[RANDSTR]' AS NUMERIC) END)) IS NULL</payload>
    </request>
    <response>
        <comparison>OR (SELECT (CASE WHEN ([RANDNUM]=[RANDNUM1]) THEN NULL ELSE CAST('[RANDSTR]' AS NUMERIC) END)) IS NULL</comparison>
    </response>
    <details>
        <dbms>PostgreSQL</dbms>
    </details>
</test>

以上测试模型,至少会发送两个Payload,第一个为<payload>里的内容,第二个为<comparison>里的内容。

但布尔盲注并非是简单地根据两个请求的内容是否存在差异,来判定dbms是否为PostgreSQL。

首先,定义<payload>为真逻辑请求(如1=1),<comparison>为假逻辑请求(1=2),则布尔盲注判断分析:

!以下为自己的理解,欢迎大家一起交流。

'真逻辑请求页面与正常页面不同' 
=> 真逻辑请求被当作变量值处理,而不是逻辑运算 => #未能注入

'真逻辑请求页面与正常页面相同' & '真假逻辑请求页面相同' 
=> 注入代码被过滤,或重定向至同一页面 => #未能注入

'真逻辑请求页面与正常页面相同' & '真假逻辑请求页面不同' & '假逻辑请求页面与正常页面相同'  
=> 判断逻辑冲突,说明区分不稳定,需补充--string/--no-string/正则 => #未能注入

'真逻辑请求页面与正常页面相同' & '真假逻辑请求页面不同' & '假逻辑请求页面与正常页面不同'  & '无随机内容'
=> 真逻辑请求解析正常,假逻辑请求解析错误,即可进行逻辑运算 => 存在注入!

'真逻辑请求页面与正常页面相同' & '真假逻辑请求页面不同' & '假逻辑请求与正常页面不同'  & '有随机内容' & '错误请求页面与正常页面相同' 
=> 随机生成的内容有运行正常的,也有运行失败的。而假逻辑若能逻辑运算,则一定运行错误。
   那么包含随机内容的假逻辑能逻辑运算,也一定运行错误。(True && False = False , False && False = False)
   若错误请求页面与正常页面相同,那么假逻辑请求与正常页面也应该相同。但这里判断逻辑冲突,说明注入失败 => #未能注入

'真逻辑请求页面与正常页面相同' & '真假逻辑请求页面不同' & '假逻辑请求页面与正常页面不同'  & '有随机内容' & '错误请求页面与正常页面不同' 
=> 真逻辑请求解析正常,错误请求解析错误,假逻辑请求也解析错误,即可进行逻辑运算 => 存在注入!

布尔盲注逻辑 布尔盲注实现代码

XSS与FI检测

在启发式 sql 注入检测完毕之后,会执行其他的检测。例如XSS和FileInclude:


细节性内容

测试数据模型
<test>
    <title></title>     # 测试的名称,这些名称在测试的时候会输出在日志中
    <stype></stype>     # 表示注入的类型
                            1: Boolean-based blind SQL injection
                            2: Error-based queries SQL injection
                            3: Inline queries SQL injection
                            4: Stacked queries SQL injection
                            5: Time-based blind SQL injection
                            6: UNION query SQL injection
    <level></level>     # 测试的级别
                            1: Always (<100 requests)
                            2: Try a bit harder (100-200 requests)
                            3: Good number of requests (200-500 requests)
                            4: Extensive test (500-1000 requests)
                            5: You have plenty of time (>1000 requests)
    <risk></risk>       # 表明对目标数据库的损坏程度
                            1: Low risk
                            2: Medium risk
                            3: High risk 可修改,甚至删除数据。
    <clause></clause>   # 表明测试 Payload 适用于SQL哪种语句。
                            0: Always
                            1: WHERE / HAVING
                            2: GROUP BY
                            3: ORDER BY
                            4: LIMIT
                            5: OFFSET
                            6: TOP
                            7: Table name
                            8: Column name
                            9: Pre-WHERE (non-query)
    <where></where>     # 怎么加入<prefix> <payload><comment> <suffix> 内容
                            1: 添加到原参数后。如 id=1<prefix> <payload><comment> <suffix>
                            2: Replace the parameter original value with a negative random integer value and append our string
                               将原参数替换成一个随机的负数,然后再添加到后面。如 id=[-RANDNUM]<prefix> <payload><comment> <suffix>
                            3: 直接替换原参数。如id=<prefix> <payload><comment> <suffix>
    <vector></vector>   # 描述Payload格式,大概是什么样子。
    <request>           # 关于发起请求的设置与配置
        <payload></payload>   # 实际测试使用的 Payload
        <comment></comment>   # 附加到Payload的注释符号,在<suffix>之前。
        <char></char>         # 只有 UNION 注入存在的字段。指定用于爆破columns个数的参数字
        <columns></columns>   # 只有 UNION 注入存在的字段。指定要测试的列的范围
    </request>
    <response>          # 关于请求结果的处理方式
        <comparison></comparison> # 针对布尔盲注的特有字段,表示对比和 request 中请求的结果。
        <grep></grep>             # 针对报错型注入的特有字段,使用正则表达式去匹配结果。
        <time></time>             # 针对时间盲注
        <union></union>           # 处理 UNION 注入的办法。
    </response>
    <details>           # 指明如果 response 标签中的检测结果成功了,可以推断出什么结论?
        <dbms></dbms>                  # 数据库类型
        <dbms_version></dbms_version>  # 数据库版本
        <os></os>                      # 系统
    </details>
</test>

详细说明

Boundary边界模型
<boundary>
    <level></level> 
    <clause></clause>
    <where></where>
    <ptype></ptype>    # 参数类型(上下文类型)
                           1: Unescaped numeric  无范围数字
                           2: Single quoted string  单引号字符串
                           3: LIKE single quoted string 类单引号字符串
                           4: Double quoted string 双引号字符串
                           5: LIKE double quoted string 类双引号字符串
    <prefix></prefix>  # Payload前缀
    <suffix></suffix>  # Payload后缀
</boundary>

待续

上一篇 下一篇

猜你喜欢

热点阅读