频道栏目
首页 > 安全 > 网站安全 > 正文

phpcms v9 2013-02-01会员中心注入漏洞分析报告(含临时方案)

2013-02-02 10:11:16         来源:Seay网络安全博客   作者:Seay
收藏   我要投稿

报告名称:phpcms v9 2013-02-01 会员中心注入漏洞分析报告

漏洞作者:skysheep

分析作者:Seay

博客:http://www.cnseay.com/

漏洞分析:
漏洞存在于 phpcms\modules\member\index.php 文件account_manage_info函数,其功能是更新会员信息。

  
public function account_manage_info() {
 
       if(isset($_POST['dosubmit'])) {
 
           //更新用户昵称
 
           $nickname = isset($_POST['nickname']) && trim($_POST['nickname']) ? trim($_POST['nickname']) : '';
 
           if($nickname) {
 
              $this->db->update(array('nickname'=>$nickname), array('userid'=>$this->memberinfo['userid']));
 
              if(!isset($cookietime)) {
 
                  $get_cookietime = param::get_cookie('cookietime');
 
              }
 
              $_cookietime = $cookietime ? intval($cookietime) : ($get_cookietime ? $get_cookietime : 0);
 
              $cookietime = $_cookietime ? TIME + $_cookietime : 0;
 
              param::set_cookie('_nickname', $nickname, $cookietime);
 
           }
 
           require_once CACHE_MODEL_PATH.'member_input.class.php';
 
           require_once CACHE_MODEL_PATH.'member_update.class.php';
 
           $member_input = new member_input($this->memberinfo['modelid']);
 
           $modelinfo = $member_input->get($_POST['info']);
 
           $this->db->set_model($this->memberinfo['modelid']);
 
           $membermodelinfo = $this->db->get_one(array('userid'=>$this->memberinfo['userid']));
 
           if(!empty($membermodelinfo)) {
 
              $this->db->update($modelinfo, array('userid'=>$this->memberinfo['userid']));
 
           } else {
 
              $modelinfo['userid'] = $this->memberinfo['userid'];
 
              $this->db->insert($modelinfo);
 
           }

代码中:$modelinfo = $member_input->get($_POST['info']);取得提交上来的会员模型中的字段,我们跟进member_input类中的get()函数看看,

在\caches\caches_model\caches_data\ member_input.class.php 文件中:

 

?[Copy to clipboard]View Code PHP
 
function get($data) {
 
       $this->data = $data = trim_script($data);
 
       $model_cache = getcache('member_model', 'commons');
 
       $this->db->table_name = $this->db_pre.$model_cache[$this->modelid]['tablename'];
 
       $info = array();
 
       $debar_filed = array('catid','title','style','thumb','status','islink','description');
 
       if(is_array($data)) {
 
           foreach($data as $field=>$value) {
 
              if($data['islink']==1 && !in_array($field,$debar_filed)) continue;
 
              $name = $this->fields[$field]['name'];
 
              $minlength = $this->fields[$field]['minlength'];
 
              $maxlength = $this->fields[$field]['maxlength'];
 
              $pattern = $this->fields[$field]['pattern'];
 
              $errortips = $this->fields[$field]['errortips'];
 
              if(empty($errortips)) $errortips = "$name 不符合要求!";
 
              $length = empty($value) ? 0 : strlen($value);
 
              if($minlength && $length < $minlength && !$isimport) showmessage("$name 不得少于 $minlength 个字符!");
 
              if($maxlength && $length > $maxlength && !$isimport) {
 
                  showmessage("$name 不得超过 $maxlength 个字符!");
 
              } else {
 
                  str_cut($value, $maxlength);
 
              }
 
              if($pattern && $length && !preg_match($pattern, $value) && !$isimport) showmessage($errortips);
 
                if($this->fields[$field]['isunique'] && $this->db->get_one(array($field=>$value),$field) && ROUTE_A != 'edit') showmessage("$name 的值不得重复!");
 
              $func = $this->fields[$field]['formtype'];
 
              if(method_exists($this, $func)) $value = $this->$func($field, $value);
 
              $info[$field] = $value;
 
           }
 
       }
 
       return $info;
 
    }

trim_script函数是过滤XSS的,上面get函数一段代码干的事就是取提交上来的字段和值重新赋值到数组,

 

再到phpcms\modules\member\index.php 文件account_manage_info函数

过了get()函数之后。

?[Copy to clipboard]View Code PHP
 
$modelinfo = $member_input->get($_POST['info']);
 
           $this->db->set_model($this->memberinfo['modelid']);
 
           $membermodelinfo = $this->db->get_one(array('userid'=>$this->memberinfo['userid']));
 
           if(!empty($membermodelinfo)) {
 
              $this->db->update($modelinfo, array('userid'=>$this->memberinfo['userid']));
 
           } else {

直接带入数据库,update函数我们跟进看看

?[Copy to clipboard]View Code PHP
 
public function update($data, $table, $where = '') {
 
       if($table == '' or $where == '') {
 
           return false;
 
       }
 
       $where = ' WHERE '.$where;
 
       $field = '';
 
       if(is_string($data) && $data != '') {
 
           $field = $data;
 
       } elseif (is_array($data) && count($data) > 0) {
 
           $fields = array();
 
           foreach($data as $k=>$v) {
 
              switch (substr($v, 0, 2)) {
 
                  case '+=':
 
                     $v = substr($v,2);
 
                     if (is_numeric($v)) {
 
                         $fields[] = $this->add_special_char($k).'='.$this->add_special_char($k).'+'.$this->escape_string($v, '', false);
 
                     } else {
 
                         continue;
 
                     }
 
                     break;
 
                  case '-=':
 
                     $v = substr($v,2);
 
                     if (is_numeric($v)) {
 
                         $fields[] = $this->add_special_char($k).'='.$this->add_special_char($k).'-'.$this->escape_string($v, '', false);
 
                     } else {
 
                         continue;
 
                     }
 
                     break;
 
                  default:
 
                     $fields[] = $this->add_special_char($k).'='.$this->escape_string($v);
 
              }
 
           }
 
           $field = implode(',', $fields);
 
       } else {
 
           return false;
 
       }
 
       $sql = 'UPDATE `'.$this->config['database'].'`.`'.$table.'` SET '.$field.$where;
 
       print_r($sql);
 
       return $this->execute($sql);
 
    }

从头到尾也是没有验证数据库是否存在数组中的字段,然后直接执行SQL语句。也就是说SQL语句中的字段我们可控,导致注入。

 

攻击测试:

测试地址 http://localhost

  注册会员seay并登陆。打开firebug工具HTML选项。修改birthday的name值为注入语句


 1


www.2cto.com补充临时解决方案:
暂时先去掉该功能吧
修改如下:
public function account_manage_info() {
  
  include template('member', 'account_manage_info');
  exit();
  if(isset($_POST['dosubmit'])) {
   //更新用户昵称
 

上一篇:利用post在Ecshop后台getshell的方法
下一篇:Jeecms变形记:xss变种到csrf再变种webshell(jeecms漏洞集合)
相关文章
图文推荐

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站