美文网首页
SQLMAP 流程分析

SQLMAP 流程分析

作者: Franchen | 来源:发表于2019-03-19 09:47 被阅读0次

SQLMAP运行流程

0x00 CheckWAF

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

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

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

  • 最常见形式 %20、+、/**/
  • Mysql中可以利用的空白字符有:%09,%0a,%0b,%0c,%0d,%20,%a0
  • 内联注释 /!12345select/
    参见

然后自己写tamper


0x01 checkStability

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

  • 使用--string或--not-string来通过识别指定字符串是否存在,来比较页面
  • 使用正则来比较页面
  • 自动检测并移除动态内容进行比较页面。移除方法是记录动态内容前后内容,每次比较页面前,先移除动态内容。

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

  • 参数排序
  • 参数过滤
    • 排除已经检查过的参数
    • 排除随机化参数
    • 排除已忽略参数
    • 排除设置中不需要检查的参数
    • 排除CSRFToken
    • 按照level忽略session-like参数
  • 检查动态参数 checkDynParam

0x03 启发式 sql 注入判断

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

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

  • nullConnection 指的是一种不需要知道他的具体内容就可以知道整个内容大小的请求方法。
  • heavilyDynamic 指的是,在不改变任何参数的情况下,请求两次页面,两次页面的相似度低于 0.98。

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

  • casting 不存在注入,或在不考虑 tamper 的情况下无法检测/绕过。这个标识位主要取决于两种情况:

    • 第一种:在第一个请求就发现存在了特定的类型检查的迹象;例如is_int($_GET('num'))
    • 第二种:在请求小数情况的时候,发现小数被强行转换为整数。例如intval($_GET('num'))
  • result 可能存在注入,这个标识位取决于

    • 检测出 DBMS 错误,则会设置这个标识位为 True;
    • 出现了数据库执行数值运算,也置为 True。

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>,涉及:

  • Tamper:对<payload>进行处理,实现Bypass各种防火墙。
  • Render:对<payload>中随机化的标签进行渲染和替换。例如:[INFERENCE]=>布尔等式;[RANDSTR]=>随机字符串;[RANDNUM]=>随机数字;[SLEEPTIME]=>随机时长。
  1. 过滤与排除不合适的测试用例。
  1. 将筛选出的边界与预处理后的 payload 整合

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

  1. payload 渲染。
  1. 针对四种类型的注入分别进行 response 的响应和处理。
  • 布尔注入(boolean-base)
  • 错误注入(error-base)
  • 时间注入(time-base)
  • 联合注入(union query) / 行内注入(Inline queries)/ 嵌套注入(Stacked queries)
  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:

  • 检测 XSS 的方法其实就是检查 “<‘\”>”,是否出现在了结果中。作为扩展,我们可以在此检查是否随机字符串还在页面中,从而判断是否存在 XSS 的迹象。
  • 检测 FI(文件包含),就是检测结果中是否包含了 include/require 等报错信息,这些信息是通过特定正则表达式来匹配检测的。

细节性内容

测试数据模型
<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>

待续

相关文章

网友评论

      本文标题:SQLMAP 流程分析

      本文链接:https://www.haomeiwen.com/subject/fobauqtx.html