PHPCMS V9 /phpcms/modules/vote/index.php 代码执行漏洞

基本字段

漏洞编号:
SSV-89119
披露/发现时间:
2015-03-30
提交时间:
2015-04-14
漏洞等级:
漏洞类别:
代码执行
影响组件:
phpcms
(漏洞影响:,PHPCMS V9)
漏洞作者:
未知
提交者:
k0shl
CVE-ID:
补充
CNNVD-ID:
补充
CNVD-ID:
补充
ZoomEye Dork:
补充

来源

漏洞详情

贡献者 Knownsec 共获得  5.3KB

漏洞影响版本:phpcms v9.5.8

漏洞分析:hpsso/index.php文件所有的操作都存在严重的注入问题,这个类文件的构造函数最先调用它的父构造函数,通过auth_key来解析POST传入的data内容,解析后data中的内容会作为注册、登陆、删除用户等操作的内容依据,而这些操作都会将这些数据作为数据库查询语句使用。这个问题其实在XXX的《PHPCMS V9 最新版本配置文件未授权访问读取》中已经体现出来了,不过他仅仅只是分析了信息泄露的问题,而忽略的他利用所使用的注入问题。

我们以phpsso的login流程为例来看这个问题,先看phpsso的解析数据部分的代码:

if(isset($_POST['appid'])) {
      $this->appid = intval($_POST['appid']);
  } else {
      exit('0');
  }


  if(isset($_POST['data'])) {
      parse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);
      if(empty($this->data) || !is_array($this->data)) {
          exit('0');

在auth_key解码之后使用parse_str解析成数组格式,这段代码如果在php5.3之前的情况下是没有问题的,因为默认情况下parse_str会启动gpc机制对特殊字符进行转义。但是在php5.3之后gpc机制默认就关闭掉了,这就导致如果解析出来的内容如果带有单引号这类个特殊字符,就原封不动的放到的变量中,这导致了注入的风险。下面我们简单来看一下login行为的代码:

public function login() {
  $this->password = isset($this->data['password']) ? $this->data['password'] : '';
  $this->email = isset($this->data['email']) ? $this->data['email'] : '';
  if($this->email) {
      $userinfo = $this->db->get_one(array('email'=>$this->email));
  } else {
      $userinfo = $this->db->get_one(array('username'=>$this->username));
  }

  if ($this->config['ucuse']) {
      pc_base::load_config('uc_config');
      require_once PHPCMS_PATH.'api/uc_client/client.php';
      list($uid, $uc['username'], $uc['password'], $uc['email']) = uc_user_login($this->username, $this->password, 0);
  }

  if($userinfo) {
      //ucenter登陆部份
      if ($this->config['ucuse']) {
          if($uid == -1) {  //uc不存在该用户,调用注册接口注册用户
              $uid = uc_user_register($this->username , $this->password, $userinfo['email'], $userinfo['random']);
              if($uid >0) {
                  $this->db->update(array('ucuserid'=>$uid), array('username'=>$this->username));
              }
          }
      }

所有$this->data的内容没有经过任何处理就直接参数到数据库查询当中,如果我们有auth_key的话,完全可以构造带有恶意的内容提交造成SQL注入漏洞。那么如果没有auth_key怎么办呢?我们可以让使用auth_key的页面帮我们编码,甚至帮助我们提交。因此下面这个看似无关紧要的问题,就成了导致注入必不可少的一步。

说了这么多,终于可以开始入正题了。我们来跟一下登陆的流程,先看member/index.php文件中的login方法:

 $username = isset($_POST['username']) && is_username($_POST['username']) ? trim($_POST['username']) : showmessage(L('username_empty'), HTTP_REFERER);
      $password = isset($_POST['password']) && trim($_POST['password']) ? trim($_POST['password']) : showmessage(L('password_empty'), HTTP_REFERER);
      $cookietime = intval($_POST['cookietime']);
      $synloginstr = ''; //同步登陆js代码

      if(pc_base::load_config('system', 'phpsso')) {
          $this->_init_phpsso();
          $status = $this->client->ps_member_login($username, $password);
          $memberinfo = unserialize($status);

通过这段代码我们需要注意到三个地方,首先是username使用的is_username进行了过滤而password没有做任何处理,然后通过client的ps_member_login方法获取一段数据。最需要关注的是最后一个地方,之后所有操作的内容就完全使用的返回的这套数据。

下面我们继续来看ps_member_login这个方法的代码:

public function ps_member_login($username, $password, $isemail=0) {
      if($isemail) {
          if(!$this->_is_email($username)) {
              return -3;
          }
          $return = $this->_ps_send('login', array('email'=>$username, 'password'=>$password));
      } else {
          $return = $this->_ps_send('login', array('username'=>$username, 'password'=>$password));
      }
      return $return;
  }

private function _ps_send($action, $data = null) {
      return $this->_ps_post($this->ps_api_url."/index.php?m=phpsso&c=index&a=".$action, 500000, $this->auth_data($data));
  }

可以看出使用_ps_post这个方法向phpsso机制的请求login行为,也就是说member的认证其实是有phpsso来完成的。而phpsso的认证数据是需要auth_key编码的,那么这个过程就很直接的呈现在我们眼前:登录用户提交用户名和密码给menber的login,然后member的login通过ps_member_login构造发送phpsso请求login验证的http包,并且将用户名和密码使用auth_key进行编码,作为http包的post数据,phpsso认证完成后,将用户的信息返回给member的login进行后续处理。

上面的这个过程中我们需要牢记的一点,就是password没有做任何处理。带着这一点,我们再回头看phpsso的login注入问题点,就可以很明确的发现通过password能够造成注入问题。

我们在这里简单总结下漏洞原因,首先member的login没有对password做过滤便带入到phpsso的login中进行验证,然后phpsso没有对于解码数据进行过滤,从而导致SQL注入。

k0shl Rainy ggbond Hoyann lightning1141 flsf 00r00 RickGray 等 42  兑换了

PoC (pocsuite 插件) (pocsuite 插件)

贡献者 Knownsec 共获得   15KB
登陆后兑换查看

k0shl Rainy ggbond Hoyann RickGray 00r00 flsf 等 11 兑换

参考链接

解决方案

临时解决方案

升级至官方最新版

官方解决方案

暂无官方解决方案

防护方案

参数的转义和过滤

人气 5338
评论前需绑定手机 现在绑定

全部评论 (1)

※本站提供的任何内容、代码与服务仅供学习,请勿用于非法用途,否则后果自负