漏洞原理
ThinkPHP未对数组的key进行过滤,导致在构造SQL的order by部分时,将关联数组的key进行拼接,导致SQL注入。
漏洞影响
ThinkPHP v3.x
ThinkPHP v5.x < ThinkPHP v5.1.22
漏洞分析
ThinkPHP v5.1.22
library/think/db/Builder.php
/**
* order分析
* @access protected
* @param Query $query 查询对象
* @param mixed $order
* @return string
*/
protected function parseOrder(Query $query, $order)
{
if (empty($order)) {
return '';
}
$array = [];
foreach ($order as $key => $val) {
if ($val instanceof Expression) {
$array[] = $val->getValue();
} elseif (is_array($val)) {
$array[] = $this->parseOrderField($query, $key, $val);
} elseif ('[rand]' == $val) {
$array[] = $this->parseRand($query);
} else {
if (is_numeric($key)) {
list($key, $sort) = explode(' ', strpos($val, ' ') ? $val : $val . ' ');
} else {
$sort = $val;
}
$sort = strtoupper($sort);
$sort = in_array($sort, ['ASC', 'DESC'], true) ? ' ' . $sort : '';
$array[] = $this->parseKey($query, $key, true) . $sort;
}
}
return ' ORDER BY ' . implode(',', $array);
}
/**
* 字段名分析
* @access public
* @param Query $query 查询对象
* @param mixed $key 字段名
* @param bool $strict 严格检测
* @return string
*/
public function parseKey(Query $query, $key, $strict = false)
{
return $key instanceof Expression ? $key->getValue() : $key;
}
可以看到,如果$order
中的$key
直接拼接到了SQL语句中。
若提交order['username|updatexml(1,concat(0x7e,(version())),0)%23']
那么,拼接后的SQL语句就注入了我们的代码了。
貌似最近有不少因为$key未过滤引发的SQL注入漏洞,是一个很少人考虑到要过滤的点。
参考
https://mp.weixin.qq.com/s/jDvOif0OByWkUNLv0CAs7w
https://www.seebug.org/vuldb/ssvid-97512
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至3213359017@qq.com