cdxy.me
Footprints on Cyber Security and Python

背景

在缺失其他维度日志的情况下,仅依据HTTP请求日志,对SQL盲注入侵成功的事件进行告警。

核心思路由 @xs大佬 @高渐离 提供。

介绍

盲注:注入过程中无回显,只能通过侧信道判断每条SQL指令的运算结果是True或False。在这种情况下想要偷取到对方数据库的数据,一般的利用方法是将信息按字符切分,然后将字符的ascii码和数字利用二分法比对,直到dump出整条数据的内容,即"按位爆破"。

时间盲注

select sleep(find_in_set(mid(@@version, 1, 1), '0,1,2,3,4,5,6,7,8,9,.'));

id=1 union select 1,benchmark(1000000,md5(1)),1 from use where  userid=1 and ord(substring(username,1,1))=97 /*

布尔盲注

http://localhost/sqlilabs/Less-8/?id=2' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>60 %23

"按位爆破"过程中的SQL语法结构是不变的,发生变化的只有纯数字参数,即字符串index位置和二分法猜测ascii的值,如下图红色部分。

图片

因此检测此类攻击的思路是统计同一个语法结构对应的不同payload数量。可按SQL语法结构做tokenize,然后统计每个token对应的不同payload次数,超过一定阈值时认为在“按位爆破”。

此类dump数据的行为已经进入到Breach/Post-Breach阶段,可定性为攻击成功。

实现

这类payload的实现需要利用到mysql内置的切割字符的函数,此类函数有:substr,substring,substring_index,left,right,mid

数据分析流程:

  1. 用粗粒度WAF规则过滤出HTTP日志中疑似SQL注入的攻击流量。
  2. 用上面提到的黑名单函数过滤1的结果,得到原始payload。
    gjz=-9031%25%27%20OR%20ORD%28MID%28%28IFNULL%28CAST%28VERSION%28%29%20AS%20CHAR%29%2C0x20%29%29%2C6%2C1%29%29%3E47%20AND%20%27%25%27%3D%27
  3. 解码。
    gjz=-9031%' OR ORD(MID((IFNULL(CAST(VERSION() AS CHAR),0x20)),6,1))>47 AND '%'='
  4. 提取MID()函数的内容。
    (ifnull(cast(version() as char),0x20)),6,1
  5. 用正则将4结果字符串中包含的数字替换为空,存为token。
  6. 将数据按5的结果分组,统计每个分组内第4步的不同payload数量。
  7. 设定阈值,当6的统计结果超过该值时产出告警。

REF

  • https://dev.mysql.com/doc/refman/8.0/en/string-functions.html
  • 《KCon 2017: WEB日志大数据安全分析实战》 - @高渐离