V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
wangyu4882
V2EX  ›  软件

分析 SQL 执行记录,发现 SQL 中的注入点

  •  
  •   wangyu4882 · 2016-08-23 10:47:21 +08:00 · 3374 次点击
    这是一个创建于 3044 天前的主题,其中的信息可能已经有所发展或是发生改变。

    不只一次有人对我说: SQL 注入已经过时了。 现在的 WEB 应用已经很难被注入了。 还好最近看到一份针对乌云漏洞库的统计数据乌云数据分析 其结果明确的指出 SQL 注入漏洞仍然是目前 WEB 应用中数量最多的漏洞。 亡羊补牢,不如思患预防,最完美解决 SQL 注入的方法是程序中没有 SQL 注入点。即程序中不使用字符串拼接 SQL ,而全部使用占位符动态绑定参数。

    为了实现上述目标。需要开发工程师的严格自律 (不可信任),和对代码进行严格的 review (额外成本). 为了提高发现 SQL 注入点的效率。我们尝试分析Datahekr审计功能中记录的 SQL 执行记录,以自动化的方式发现 SQL 中存在的注入点。分析步骤如下:

    1. 分析 SQL

    以如下 SQL 为例。

    SELECT * FROM city_list WHERE CITY_NAME_EN = 'aaaa' and CITY_NAME_CN = ?
    SELECT * FROM city_list WHERE substring(CITY_NAME_EN,2,1) = ?
    SELECT * FROM city_list WHERE substring(CITY_NAME_EN,2,1) = ?
    SELECT * FROM city_list WHERE CITY_NAME_EN = 'SH' and CITY_NAME_CN = ?
    SELECT * FROM city_list WHERE CITY_NAME_EN = 'BJ' and CITY_NAME_CN = ?
    SELECT * FROM city_list WHERE CITY_NAME_EN = ? and CITY_NAME_CN = '上海'
    

    我们先进行 SQL 的解析。取得 SQL 中 hardcode 的数值,并对 hardcode 的参数进行参数化替换,得到如下结果。

    SELECT * FROM city_list WHERE CITY_NAME_EN = ?0 and CITY_NAME_CN = ?
    ?0 = 'aaaa'
    
    SELECT * FROM city_list WHERE substring(CITY_NAME_EN, ?0, ?1) = ?
    ?0 = 2, ?1 = 1, 
    
    SELECT * FROM city_list WHERE substring(CITY_NAME_EN, ?0, ?1) = ?
    ?0 = 2, ?1 = 1, 
    
    SELECT * FROM city_list WHERE CITY_NAME_EN = ?0 and CITY_NAME_CN = ?
    ?0 = 'SH'
    
    SELECT * FROM city_list WHERE CITY_NAME_EN = ?0 and CITY_NAME_CN = ?
    ?0 = 'BJ'
    
    SELECT * FROM city_list WHERE CITY_NAME_EN = ? and CITY_NAME_CN = ?0
    ?0 = '上海'
    

    2. 合并相同结构 SQL ,并统计 hardcode 参数中出现的不同参数值。

    SELECT * FROM city_list WHERE CITY_NAME_EN = ?0 and CITY_NAME_CN = ?
    ?0 = 'aaaa','SH','BJ'
    
    SELECT * FROM city_list WHERE substring(CITY_NAME_EN, ?0, ?1) = ?
    ?0 = 2, ?1 = 1
    
    SELECT * FROM city_list WHERE CITY_NAME_EN = ? and CITY_NAME_CN = ?0
    ?0 = '上海'
    

    SELECT * FROM city_list WHERE CITY_NAME_EN = ?0 and CITY_NAME_CN = ?
    

    的参数 ?0 中,出现了 3 个不同的参数值,所以预测

    SELECT * FROM city_list WHERE CITY_NAME_EN = 'aaaa' and CITY_NAME_CN = ?
    

    中 'aaaa' 处存在注入点。

    在其他 SQL 中,虽然也存在 hardcode 的数值,但是没有出现不同的数值。所以不认为是 SQL 注入点。

    注意点 1 :

    SQL 中可能出现枚举类型:

    SELECT * FROM city_list WHERE ACTIVE = 1 and CITY_NAME_CN = ?
    SELECT * FROM city_list WHERE ACTIVE = 0 and CITY_NAME_CN = ?
    
    SELECT * FROM city_list WHERE TYPE = 'A' and CITY_NAME_CN = ?
    SELECT * FROM city_list WHERE TYPE = 'B' and CITY_NAME_CN = ?
    SELECT * FROM city_list WHERE TYPE = 'C' and CITY_NAME_CN = ?
    

    枚举类型在 SQL 中常常是 hardcode 存在的。为了避免将枚举类型误报为 SQL 注入点。我们需要考虑 hardcode 参数值样本, 例如超过 10 个不同的值,才认为是注入漏洞。

    注意点 2 :

    对于 Mysql ,因为默认 useServerPrepStmts = false,

    (请参考 http://blog.csdn.net/axman/article/details/6913527),

    导致所有发送到 DB 的 SQL 中都不包含动态参数,全部参数值都被替换入 SQL 文本中. 所以无法通过本文所述的方法进行 SQL 注入点分析。

    请先开启 useServerPrepStmts = true, 才可以使用本文的方法进行分析。

    结束:

    本文提供了一个针对 SQL 执行记录的大数据分析实例,希望能抛砖引玉,发现更多针对 SQL 的大数据分析思路,分析出一些有趣的结果。

    本文提及的分析方法,已经应用于 Datahekr 中,请大家免费注册试用。

    3 条回复    2016-08-23 13:15:30 +08:00
    avichen
        1
    avichen  
       2016-08-23 11:40:14 +08:00
    消灭 0 回复
    Suclogger
        2
    Suclogger  
       2016-08-23 11:46:20 +08:00
    链接没贴好
    lzhd24
        3
    lzhd24  
       2016-08-23 13:15:30 +08:00 via Android
    this is good , i like it , thanks for sharing
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5218 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 03:49 · PVG 11:49 · LAX 19:49 · JFK 22:49
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.