PHPCMS_V9.2 任意文件上传 getshell 漏洞分析

sugar 2021-03-11
Web安全 发布于 2021-03-11 10:58:13 阅读 156 评论 0

介绍&预备知识

介绍:PHPCMS是一款网站管理软件。该软件采用模块化开发,支持多种分类方式。

预备知识

PHPCMS是采用MVC设计模式开发,基于模块和操作的方式进行访问,采用单一入口模式进行项目部署和访问,无论访问任何一个模块或者功能,只有一个统一的入口。

参数名称 描述 位置 备注
m 模型/模块名称 phpcms/modules中模块目录名称 必须
c 控制器名称 phpcms/modules/模块/*.php 文件名称 必须
a 事件名称 phpcms/modules/模块/*.php 中方法名称

模块访问方法[示例]:http://www.xxx.com/index.php?m=content&c=index&a=show&id=1

其中 m = content 为模型/模块名称 位于phpcms/modules/content

c = index 为控制器名称 位于phpcms/modules/content/index.php

a = show 为时间名称 位于phpcms/modules/content/index.phpshow()方法id = 1 为其他参数 与正常get传递参数形式相同

还有一点就是访问http://www.xxx.com/index.php

phpcms默认路由会定位到content模块的index控制器中的init操作,因为系统在没有指定模块和控制器的时候,会执行默认的模块和操作.

所以跟访问http://www.xxx.com/index.php?m=content&c=index&a=init是一样的

参考来源:http://www.sjzphp.com/webdis/router_url_90...

环境搭建&所需工具

  • phpstudy2018

  • php-5.4.45-nts + Apache

  • PHPCMS_V9.2

  • Burpsuite2.1,2021年最新那个burp编码有问题(可能我没调好),数据乱码,导致上传错误

测试站点网址:www.phpcms92.com

访问/install/install.php文件进行安装,下一步

图片

下一步,配置相关信息

图片

图片

安装完成!!!

漏洞复现

访问首页index.php

图片

注册一个账户(这里我以Tao这个普通用户进行演示)

图片

到个人主页修改头像处,上传头像

图片

在此之前,还要准备一个后缀为zip的压缩包,具体内容如下:

图片

php文件需要放在二层目录下然后再进行压缩

上传头像照片(Burp抓包)->保存图片

将之前的图片数据删除

图片

图片

Tao.zip中数据,按照上图的操作添加至请求中,最终效果如下图。然后放行

图片

访问phpsso_server/uploadfile/avatar/1/1/1/dir/404.php(这里的1是注册后用户的id)

图片

漏洞分析

在分析之前,我们先说一下漏洞存在处的功能,执行流程,以及漏洞产生的原因。

在编辑头像处,我们上传头像,前端会将我们上传的图片进行分割成三张(三个尺寸大小)。然后前端打包压缩成zip数据,当我们保存图片时,我们的压缩包数据会上传到服务器,通过uploadavatar函数进行处理(函数在文件phpsso_server/phpcms/modules/phpsso/index.php);而这个函数的执行流程就是:

  1. 在保存上传头像文件夹处,创建一个跟用户id对应的文件夹

  2. 将前端打包的压缩包通过post传来的数据进行保存,保存名为用户id的zip文件

  3. 解压数据包

  4. 判断未在数组内文件名命名的文件,不是则通过unlink函数遍历删除

上面流程存在问题的地方有,1.未对压缩包内容进行处理,2.解压遍历删除使用的是unlink函数,这个函数只能删除文件,不能删除文件夹。因为这一原因,我们只需将压缩包文件里带一个目录,目录里带恶意文件,即可绕过。

图片

图片处理请求为/phpsso_server/index.php?m=phpsso&c=index&a=uploadavatar

定位文件phpsso_server/phpcms/modules/phpsso/index.php572行

为什么定位到这,开头介绍有说

图片

调试,向下执行

public function uploadavatar() {

//根据用户id创建文件夹
if(isset($this->data[‘uid’]) && isset($this->data[‘avatardata’])) {
$this->uid = $this->data[‘uid’];
$this->avatardata = $this->data[‘avatardata’];
} else {
exit(‘0’);

图片

可以发现$this->data['avatardata']变量存储着我们上传修改的数据(恶意)

$this->data['avatardata']是通过伪协议获取的(文件为phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php),具体代码如下:

$postStr = file_get_contents(“php://input”);
if($postStr) {
$this->data[‘avatardata’] = $postStr;

继续向下走,新建存放图片目录

图片

//创建图片存储文件夹
$avatarfile = pc_base::load_config(‘system’, ‘upload_path’).’avatar/‘;
$dir = $avatarfile.$dir1.’/‘.$dir2.’/‘.$this->uid.’/‘;
if(!file_exists($dir)) {
mkdir($dir, 0777, true);
}
$filename = $dir.$this->uid.’.zip’;

上面代码第五行创建目录。之后进行新命名压缩包,名为用户id值。然后将我们上面通过伪协议获取的数据进行写入

图片

如下图,可以发现,新建了1.zip

图片

压缩包内容如下,就是我们修改上传的数据

图片

之后解压缩。。。

图片

走到遍历白名单判断文件,排除.(当前目录)..(上级目录)

图片

图片

下图删除了压缩包文件

图片

继续执行,当判断到dir目录时,因为dir目录不属于数组里(白名单),然后执行unlink(dir目录)。由于unlink函数只能删除文件,无法删除文件夹,所以就留下了恶意代码文件。

图片

接着跳出了if语句,继续执行,将信息更新至数据库

图片

所以,漏洞产生的原因就是unlink函数

if(!in_array($file, $avatararr)) {

图片

因为unlink无法删除文件夹,这就是为什么上面利用的压缩包里的恶意代码文件需要放在目录下

漏洞修复

  • 不使用zip压缩包处理图片文件

  • 使用最新版的phpcms

文章中有什么不足和错误的地方还望师傅们指正。

原创: Tao 黑白天实验室
原文链接:https://mp.weixin.qq.com/s/o_u_mFjFIq3hKgS...

本作品采用《CC 协议》,转载必须注明作者和本文链接
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!
请勿发布不友善或者负能量的内容。与人为善,比聪明更重要!