漏洞原理

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注入漏洞,是一个很少人考虑到要过滤的点。

标签: none

添加新评论