代码审计-phpok框架5.3注入漏洞

0x01 框架路由和底层过滤

路由:

入口:

index.php,api.php,admin.php

 

 

0x02 注入分析

注入成因位置:framework/model/list.php 的907行(arc_all函数当中)

$orderby可控 

发现framework/phpok_call.php中的_arclist函数中调用了arc_all 函数

        $this->cache->save($cache_id,$array);
            }
            return $array;
        }
        $orderby = $rs['orderby'] ? $rs['orderby'] : $project['orderby'];
        if(!$rs['is_list']){
            $rs['psize'] = 1;
        }
        $offset = $rs['offset'] ? intval($rs['offset']) : 0;
        $psize = $rs['is_list'] ? intval($rs['psize']) : 1;
        $rslist = $this->model('list')->arc_all($project,$condition,$field,$offset,$psize,$orderby);
        if(!$rslist){
            if($cache_id){
                $this->cache->save($cache_id,$array);
            }
            return $array;
        }
        $ids = array();
        foreach($rslist as $key=>$value){
            $ids[] = $value['id'];
            foreach($nlist as $k=>$v){
                $myval = $this->lib('form')->show($v,$value[$k]);
                if($v['form_type'] == 'url' && $value[$k]){
                    $tmp = unserialize($value[$k]);
扫描二维码关注公众号,回复: 9357041 查看本文章

_arclist函数中 $orderby变量是通过$rs来赋值的   跟踪$rs

//读取文章列表
    private function _arclist($rs,$cache_id='')
    {
        if(!$rs['pid'] && !$rs['phpok']){
            return false;
        }
        if(!$rs['pid']){
            $tmp = $this->model('id')->id($rs['phpok'],$rs['site'],true);
            if(!$tmp || $tmp['type'] != 'project'){
                unset($tmp,$rs);
                return false;
            }
            $rs['pid'] = $tmp['id'];
            unset($tmp);
        }
        if(!$rs['pid']){
            unset($rs);
            return false;
        }
        $project = $this->_project(array('pid'=>$rs['pid'],'site'=>$rs['site']));
        if(!$project || !$project['status'] || !$project['module']){
            return false;
        }
        $module = $this->model('module')->get_one($project['module']);
        if(!$module || $module['status'] != 1){
            return false;
        }
        //如果使用了独立模块
        if($module['mtype']){
            return $this->_arclist_single($rs,$cache_id,$project,$module);
        }
        $array = array('project'=>$project);
        $this->model('list')->is_biz($project['is_biz']);
        $this->model('list')->is_biz($project['is_userid']);
        $this->model('list')->multiple_cate(0);
        if($project['cate']){
            $this->model('list')->multiple_cate($project['cate_multiple']);
        }
        if($project['cate'] || $rs['cateid']){
            $cateid = $rs['cateid'] ? $rs['cateid'] : $project['cate'];
            $cate = $this->_cate(array("pid"=>$rs['pid'],"cateid"=>$cateid,'site'=>$rs['site']));
            if($cate){
                $array['cate'] = $cate;
                $rs['cateid'] = $cateid;
            }
        }
        $flist = $this->model('module')->fields_all($project['module']);
        $nlist = array();
        if($project['cate'] && $project['cate_multiple']){
            $list_fields = $this->model('fields')->list_fields();
            $field = 'DISTINCT l.id';
            foreach($list_fields as $key=>$value){
                if($value == 'id'){
                    continue;
                }
                $field .= ",l.".$value;
            }
        }else{
            $field = "l.*";
        }
        if($rs['fields'] && $rs['fields'] != '*'){
            $tmp = explode(",",$rs['fields']);
            if($flist){
                foreach($flist as $key=>$value){
                    if(in_array($value['identifier'],$tmp)){
                        $field .= ",ext.".$value['identifier'];
                        $nlist[$value['identifier']] = $value;
                    }
                }
            }
        }else{
            if($flist){
                foreach($flist as $key=>$value){
                    $field .= ",ext.".$value['identifier'];
                    $nlist[$value['identifier']] = $value;
                }
            }
        }
        if($project['is_biz']){
            $field.= ",b.price,b.currency_id,b.weight,b.volume,b.unit";
        }
        $condition = $this->_arc_condition($rs,$flist,$project);
        $array['total'] = $this->model('list')->arc_count($project['module'],$condition);
        if(!$array['total']){
            if($cache_id){
                $this->cache->save($cache_id,$array);
            }
            return $array;
        }
        $orderby = $rs['orderby'] ? $rs['orderby'] : $project['orderby'];
        if(!$rs['is_list']){
            $rs['psize'] = 1;
        }
        $offset = $rs['offset'] ? intval($rs['offset']) : 0;
        $psize = $rs['is_list'] ? intval($rs['psize']) : 1;
        $rslist = $this->model('list')->arc_all($project,$condition,$field,$offset,$psize,$orderby);
...

发现$rs为_arclist函数传参进来的,所以跟踪谁调用了_arclist函数

 

发现在framework/api/project_control.php中load_model函数中  209行调用了_arclist函数 并且传入了$dt  所以要跟踪$dt

if(!$pageid) $pageid = 1;
        $offset = ($pageid-1) * $psize;
        $dt['offset'] = $offset;
        $dt['psize'] = $psize;
        $dt['is_list'] = 1;
        if($attr){
            $dt['attr'] = $attr;
        }
        $fields = $this->get('fields');
        if(!$fields){
            $fields = '*';
        }
        $dt['fields'] = $fields;
        $info = $this->call->phpok('_arclist',$dt);
        unset($dt);
        if(!$info['rslist']){
            $this->error(P_Lang('已是最后一条数据'));
        }
...

发现$dt[‘orderby’]是通过$sort这个变量赋值的  所以跟踪$sort

//自定义排序
        if($sort){
            $dt['orderby'] = $sort;
            $pageurl .= '&sort='.rawurlencode($sort);
            $this->rlist['sort'] = $sort;
        }
        if(substr($pageurl,-1) == "&" || substr($pageurl,-1) == "?"){
            $pageurl = substr($pageurl,0,-1);
        }
...

发现$sort是通过get函数接受   此时是在load_module函数当中

发现在framework/api/project_control.php中的index函数调用了load_module

发现存在$project $parent_rs变量 所以跟踪这两个变量

 

$tag = $this->get("tag");
        $uid = $this->get('uid','int');
        $attr = $this->get('attr');
        //价格,支持价格区间
        $price = $this->get('price','float');
        $sort = $this->get('sort');
        //读取列表信息
        $psize = $rs["psize"] ? $rs['psize'] : $this->config['psize'];
        $pageurl = $this->url($rs['identifier']);

index_f:

//栏目
    public function index_f()
    {
        $id = $this->get("id");
        if(!$id){
            $this->error(P_Lang('未指ID'));
        }
        $tmp = $this->model('id')->id($id,$this->site['id'],true);
        if(!$tmp || $tmp['type'] != 'project'){
            $this->error(P_Lang('项目不存在'));
        }
        $pid = $tmp['id'];
        if(!$this->model('popedom')->check($pid,$this->user_groupid,'read')){
            $this->error(P_Lang('您没有阅读权限,请联系网站管理员'));
        }
        $project = $this->call->phpok('_project',array('pid'=>$pid));
        if(!$project || !$project['status']){
            $this->error(P_Lang('项目不存在或未启用'));
        }
        if($project["module"] && !$project['is_api']){
            $this->error(P_Lang('此项目接口不可用'));
        }
        $this->rlist['page_rs'] = $project;
        if($project['parent_id']){
            $parent_rs = $this->call->phpok('_project',array('pid'=>$project['parent_id']));
            if(!$parent_rs || !$parent_rs['status']){
                $this->error(P_Lang('父级项目不存在或未启用'));
            }
            $this->rlist['parent_rs'] = $parent_rs;
        }
        if($project["module"]){
            $this->load_module($project,$parent_rs);
        }
        //没有进入success函数
        $this->success($this->rlist);
    }

 load_module函數需要两个变量参数,条件如下。

$project:

构造链接:

$parent_rs:

 构造链接:

 poc

猜你喜欢

转载自www.cnblogs.com/-qing-/p/12350669.html