HTTP请求日志检测SQL盲注
[Blue Team] [Data Science for Cyber Security]
背景
在缺失其他维度日志的情况下,仅依据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
数据分析流程:
- 用粗粒度WAF规则过滤出HTTP日志中疑似SQL注入的攻击流量。
- 用上面提到的黑名单函数过滤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
- 解码。
gjz=-9031%' OR ORD(MID((IFNULL(CAST(VERSION() AS CHAR),0x20)),6,1))>47 AND '%'='
- 提取
MID()
函数的内容。
(ifnull(cast(version() as char),0x20)),6,1
- 用正则将4结果字符串中包含的数字替换为空,存为token。
- 将数据按5的结果分组,统计每个分组内第4步的不同payload数量。
- 设定阈值,当6的统计结果超过该值时产出告警。
REF
- https://dev.mysql.com/doc/refman/8.0/en/string-functions.html
- 《KCon 2017: WEB日志大数据安全分析实战》 - @高渐离