代码审计-phpok框架5.3注入漏洞
2021-06-03 09:05
标签:跟踪 arclist poc framework 函数传参 数据 进入 阅读 app 路由: 入口: index.php,api.php,admin.php init.php 2804行,新建$app对象,实例化的PHPOK的主类 然后进行行为处理: 根据入口文件的不同,再调用不同的action方法。 注入成因位置:framework/model/list.php 的907行(arc_all函数当中) $orderby可控 发现framework/phpok_call.php中的_arclist函数中调用了arc_all 函数 在_arclist函数中 $orderby变量是通过$rs来赋值的 跟踪$rs 发现$rs为_arclist函数传参进来的,所以跟踪谁调用了_arclist函数 发现在framework/api/project_control.php中load_model函数中 209行调用了_arclist函数 并且传入了$dt 所以要跟踪$dt 发现$dt[‘orderby’]是通过$sort这个变量赋值的 所以跟踪$sort 发现$sort是通过get函数接受 此时是在load_module函数当中 发现在framework/api/project_control.php中的index函数调用了load_module 发现存在$project $parent_rs变量 所以跟踪这两个变量 index_f: load_module函數需要两个变量参数,条件如下。 $project: 构造链接: $parent_rs: 构造链接: 代码审计-phpok框架5.3注入漏洞 标签:跟踪 arclist poc framework 函数传参 数据 进入 阅读 app 原文地址:https://www.cnblogs.com/-qing-/p/12350669.html0x01 框架路由和底层过滤
$app = new _init_phpok();
include_once($app->dir_phpok."phpok_helper.php");
$app->init_site();
$app->init_view();
/**
* 执行应用,三个入口(前端,接口,后台)都是从这里执行,进行初始化处理
* token 及 user_id 在 phpok5.0 中将剥离,不会放在核心引挈里
**/
final public function action()
{
$this->init_assign();
$this->init_plugin();
if($this->app_id == ‘admin‘){
$this->action_admin();
exit;
}
$this->_userToken();
if($this->app_id == ‘api‘){
$this->action_api();
exit;
}
$this->action_www();
exit;
}
get函数中的过滤
final public function get($id,$type="safe",$ext="")
{
$val = isset($_POST[$id]) ? $_POST[$id] : (isset($_GET[$id]) ? $_GET[$id] : (isset($_COOKIE[$id]) ? $_COOKIE[$id] : ‘‘));
if($val == ‘‘){
if($type == ‘int‘ || $type == ‘intval‘ || $type == ‘float‘ || $type == ‘floatval‘){
return 0;
}else{
return ‘‘;
}
}
//判断内容是否有转义,所有未转义的数据都直接转义
$addslashes = false;
if(function_exists("get_magic_quotes_gpc") && get_magic_quotes_gpc()){
$addslashes = true;
}
if(!$addslashes){
$val = $this->_addslashes($val);
}
return $this->format($val,$type,$ext);
}
_addslashes:
private function _addslashes($val)
{
if(is_array($val)){
foreach($val as $key=>$value){
$val[$key] = $this->_addslashes($value);
}
}else{
$val = addslashes($val);
}
return $val;
}
format:
final public function format($msg,$type="safe",$ext="")
{
if($msg == ""){
return ‘‘;
}
if(is_array($msg)){
foreach($msg as $key=>$value){
if(!is_numeric($key)){
$key2 = $this->format($key);
if($key2 == ‘‘ || in_array($key2,array(‘#‘,‘&‘,‘%‘))){
unset($msg[$key]);
continue;
}
}
$msg[$key] = $this->format($value,$type,$ext);
}
if($msg && count($msg)>0){
return $msg;
}
return false;
}
if($type == ‘html_js‘ || ($type == ‘html‘ && $ext)){
$msg = stripslashes($msg);
if($this->app_id != ‘admin‘){
$msg = $this->lib(‘string‘)->xss_clean($msg);
}
$msg = $this->lib(‘string‘)->clear_url($msg,$this->url);
return addslashes($msg);
}
$msg = stripslashes($msg);
//格式化处理内容
switch ($type){
case ‘safe_text‘:
$msg = strip_tags($msg);
$msg = str_replace(array("\\","‘",‘"‘,""),‘‘,$msg);
break;
case ‘system‘:
$msg = !preg_match("/^[a-zA-Z][a-z0-9A-Z\_\-]+$/u",$msg) ? false : $msg;
break;
case ‘id‘:
$msg = !preg_match("/^[a-zA-Z][a-z0-9A-Z\_\-]+$/u",$msg) ? false : $msg;
break;
case ‘checkbox‘:
$msg = strtolower($msg) == ‘on‘ ? 1 : $this->format($msg,‘safe‘);
break;
case ‘int‘:
$msg = intval($msg);
break;
case ‘intval‘:
$msg = intval($msg);
break;
case ‘float‘:
$msg = floatval($msg);
break;
case ‘floatval‘:
$msg = floatval($msg);
break;
case ‘time‘:
$msg = strtotime($msg);
break;
case ‘html‘:
$msg = $this->lib(‘string‘)->safe_html($msg,$this->url);
break;
case ‘func‘:
$msg = function_exists($ext) ? $ext($msg) : false;
break;
case ‘text‘:
$msg = strip_tags($msg);
break;
default:
$msg = str_replace(array("\\","‘",‘"‘,""),array("\","'",""","<",">"),$msg);
break;
}
if($msg){
$msg = addslashes($msg);
}
return $msg;
}
进行了转义和编码 但是在api接口orderby变量拼接时不需要单引号等预定义字符闭合语句,导致转义编码失效,造成注入。
0x02 注入分析
$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]);
//读取文章列表
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);
...
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(‘已是最后一条数据‘));
}
...
//自定义排序
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);
}
...
$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‘]);
//栏目
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);
}
poc