PHITHON的公开漏洞ThinkPHP最新版本SQL注入漏洞 2016-09-06
ThinkPHP最新版本SQL注入漏洞
你们可以说上一个SQL注入漏洞有鸡肋性,确实TP的I函数会进行一定处理。
但这个洞,I函数也奈何不了了,通用到你没话说。
与上几个洞没有关系,非补丁造成。也是影响到3.1~3.2版本的。继续用onethink做演示。
如下controller即可触发SQL注入:
1 | public function test() |
为什么?
漏洞分析
我们看看代码。我从github下载的最新源码:https://github.com/liu21st/thinkphp
/ThinkPHP/Library/Think/Db/Driver.class.php 531行:
1 | // where子单元分析 |
这就是处理where条件的函数,我们看到如下片段:
1 | }elseif(preg_match('/BETWEEN/i',$val[0])){ // BETWEEN运算 |
当匹配/BETWEEN/i
和$val[0]
时,则将strtoupper($val[0])
直接插入了SQL语句。
这个匹配:preg_match('/BETWEEN/i',$val[0])
,明显是有问题的。因为这个匹配没加^$
,也就是首尾限定,所以只要我们的$val[0]
中含有between时,这个匹配就可以成立,就产生了一个SQL注入。
为了防止I函数对我们输入的过滤影响,我们看看I函数:
1 | function I($name,$default='',$filter=null,$datas=null) { |
较前些版本有些改进:
- 加了类型强制转换
$type
,但在默认情况下$type
是空的,强制类型转换是不存在的。 - 将
is_array($data) && array_walk_recursive($data,'think_filter');
放在最后一行。我们看看think_filter这个过滤函数:
1 | function think_filter(&$value){ |
这个实际上就是对我之前那个漏洞的一个解决方案,将一些关键词后面加空格。但我们看到,这个正则是存在^$
首尾限定符的。所以只有传入参数完全“等于”BETWEEN的时候才会被加上空格,而且这里加上空格也不会影响漏洞的产生,因为漏洞位置的正则没有加^$
首尾限定符。
还有一个说明:之前thinkphp出了个“错误”的补丁,这个补丁已经被官方去掉了,所以不用考虑那个补丁造成的一些干扰。
那我们回到最初那段代码:
1 | public function test() |
这个代码,我们来测试一下:
果然是有漏洞的,我们看看具体执行的SQL语句:
就在BETWEEN处。除了BETWEEN外还有IN,我就一块说明了。
Onethink演示:
细我就不说了,和之前一样。
修复方案
正则一定要写明确:
/^BETWEEN$/i