如果问一个安全/程序员如何才能防 SQL 注入问题?我想大部分人都会提到使用参数化查询,那是不是这样就高枕无忧了呢?换句话说是不是使用参数化查询后就能杜绝一切 SQL 注入问题呢?答案是否定的,参数化查询是针对参数值的绑定技术解决注入问题,而 SQL 语句中某些字段位置并不支持绑定技术,比如 ORDER BY 关键字后跟列名。当该列名的输入对用户可控时,在 SQL 注入问题上,参数化查询就束手无策了。
验证漏洞
查找疑似和 ORDER BY 关键字有关的参数,构造合适 Payload:
|
|
因为 select 1 from information_schema.tables 会返回多个行,MySQL 会报“ERROR 1242 (21000): Subquery returns more than 1 row” 的错误,从而整条语句执行失败将无结果返回。
漏洞分析
首先看下 SELECT 语法(MySQL 5.7)
|
|
可以看出一条正确 SQL 语句 ORDER BY 关键字后面可以是列名、列别名、列位置,且 ORDER BY 后面不能跟 UNION SELECT 子句,该位置的注入主要有如下姿势:
基于时间的盲注
|
|
|
|
基于布尔盲注
|
|
|
|
下图可以反映验证漏洞环节提到的情况,这也是我在测试过程中常用的验证是否存在注入点的方式。
报错注入(前提是支持报错)
|
|
其他
除了 ORDER BY 的注入外,偶尔也会碰到 LIMIT 注入,与 ORDER BY 不同的是,LIMIT 后可以接 UNION SELECT 子句,当然前提是 LIMIT 前没有 ORDER BY 关键字。
从前面的 SELECT 语法中可知,在报错注入姿势上,ORDER BY 和 LIMIT 的利用一致,都是依赖 PROCEDURE 关键字,但该方法也有局限,此方法只适用于 MySQL 小于5.6.6的5.x系列。
最后
最近在挖漏洞过程中明显感觉的常规的注入问题变少了,猜测了下原因,可能一是各种扫描器大范围的扫描,二是开发者的安全意识提高了吧。不管怎样,这是好的趋势,安全问题若不修复,就会一直躺在那直到被人发现并利用。问题变少,说明厂商和白帽子都在努力。