好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

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

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

漏洞作者:skysheep

分析作者:Seay

博客:http://HdhCmsTestcnseay测试数据/

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

   public function account_manage_info() {          if(isset($_POST['dosubmit'])) {              //更新用户昵称              $nickname = isset($_POST['nickname']) &amp;&amp; trim($_POST['nickname']) ? trim($_POST['nickname']) : '';              if($nickname) {                 $this-&gt;db-&gt;update(array('nickname'=&gt;$nickname), array('userid'=&gt;$this-&gt;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-&gt;memberinfo['modelid']);              $modelinfo = $member_input-&gt;get($_POST['info']);              $this-&gt;db-&gt;set_model($this-&gt;memberinfo['modelid']);              $membermodelinfo = $this-&gt;db-&gt;get_one(array('userid'=&gt;$this-&gt;memberinfo['userid']));              if(!empty($membermodelinfo)) {                 $this-&gt;db-&gt;update($modelinfo, array('userid'=&gt;$this-&gt;memberinfo['userid']));              } else {                 $modelinfo['userid'] = $this-&gt;memberinfo['userid'];                 $this-&gt;db-&gt;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-&gt;data = $data = trim_script($data);          $model_cache = getcache('member_model', 'commons');          $this-&gt;db-&gt;table_name = $this-&gt;db_pre.$model_cache[$this-&gt;modelid]['tablename'];          $info = array();          $debar_filed = array('catid','title','style','thumb','status','islink','description');          if(is_array($data)) {              foreach($data as $field=&gt;$value) {                 if($data['islink']==1 &amp;&amp; !in_array($field,$debar_filed)) continue;                 $name = $this-&gt;fields[$field]['name'];                 $minlength = $this-&gt;fields[$field]['minlength'];                 $maxlength = $this-&gt;fields[$field]['maxlength'];                 $pattern = $this-&gt;fields[$field]['pattern'];                 $errortips = $this-&gt;fields[$field]['errortips'];                 if(empty($errortips)) $errortips = "$name 不符合要求!";                 $length = empty($value) ? 0 : strlen($value);                 if($minlength &amp;&amp; $length &lt; $minlength &amp;&amp; !$isimport) showmessage("$name 不得少于 $minlength 个字符!");                 if($maxlength &amp;&amp; $length &gt; $maxlength &amp;&amp; !$isimport) {                     showmessage("$name 不得超过 $maxlength 个字符!");                 } else {                     str_cut($value, $maxlength);                 }                 if($pattern &amp;&amp; $length &amp;&amp; !preg_match($pattern, $value) &amp;&amp; !$isimport) showmessage($errortips);                   if($this-&gt;fields[$field]['isunique'] &amp;&amp; $this-&gt;db-&gt;get_one(array($field=&gt;$value),$field) &amp;&amp; ROUTE_A != 'edit') showmessage("$name 的值不得重复!");                 $func = $this-&gt;fields[$field]['formtype'];                 if(method_exists($this, $func)) $value = $this-&gt;$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-&gt;get($_POST['info']);              $this-&gt;db-&gt;set_model($this-&gt;memberinfo['modelid']);              $membermodelinfo = $this-&gt;db-&gt;get_one(array('userid'=&gt;$this-&gt;memberinfo['userid']));              if(!empty($membermodelinfo)) {                 $this-&gt;db-&gt;update($modelinfo, array('userid'=&gt;$this-&gt;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) &amp;&amp; $data != '') {              $field = $data;          } elseif (is_array($data) &amp;&amp; count($data) &gt; 0) {              $fields = array();              foreach($data as $k=&gt;$v) {                 switch (substr($v, 0, 2)) {                     case '+=':                        $v = substr($v,2);                        if (is_numeric($v)) {                            $fields[] = $this-&gt;add_special_char($k).'='.$this-&gt;add_special_char($k).'+'.$this-&gt;escape_string($v, '', false);                        } else {                            continue;                        }                        break;                     case '-=':                        $v = substr($v,2);                        if (is_numeric($v)) {                            $fields[] = $this-&gt;add_special_char($k).'='.$this-&gt;add_special_char($k).'-'.$this-&gt;escape_string($v, '', false);                        } else {                            continue;                        }                        break;                     default:                        $fields[] = $this-&gt;add_special_char($k).'='.$this-&gt;escape_string($v);                 }              }              $field = implode(',', $fields);          } else {              return false;          }          $sql = 'UPDATE `'.$this-&gt;config['database'].'`.`'.$table.'` SET '.$field.$where;          print_r($sql);          return $this-&gt;execute($sql);       }

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

 

攻击测试:

测试地址 http://localhost

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

  HdhCmsTest2cto测试数据 补充临时解决方案: 暂时先去掉该功能吧 修改如下: public function account_manage_info() {      include template('member', 'account_manage_info');   exit();   if(isset($_POST[' dos ubmit'])) {    //更新用户昵称  

查看更多关于phpcms v9 2013-02-01会员中心注入漏洞分析报告(含临的详细内容...

  阅读:162次