通达OA文件上传文件包含漏洞分析
2020-03-21 11:01:01 Author: mp.weixin.qq.com(查看原文) 阅读量:116 收藏


文章来源:水滴安全实验室

通达OA简介

通达OA是由北京通达信科科技有限公司研发的一款通用型OA产品,涵盖了个人事务、行政办公、流程审批、知识管理、人力资源管理、组织机构管理等企业信息化管理功能。

本次复现环境是通达OAV11.3,文件上传漏洞为全版本通杀,文件包含漏洞/ispirit/interface/gateway.php只有V11.3版本存在。

漏洞分析环境

下载OA软件地址:https://www.tongda2000.com/download/2019.php

下载安装,配置访问端口为8080

网站源码在安装目录的wwwroot目录下:

源码经过zend 5.4加密,解密

文件上传漏洞分析

根据官网发布的补丁,更新的是ispirit/im/upload.php这个文件,跟进这个文件

$P = $_POST["P"];if (isset($P) || ($P != "")) {  ob_start();  include_once "inc/session.php";  session_id($P);  session_start();  session_write_close();}else {  include_once "./auth.php";}

当传入参数P且P不为空时,包含inc/session.php获取session,否则就会包含/auth.php进行用户认证。

继续跟进upload.php,23行,29行,35行逻辑判断是否传入DEST_UID参数,若参数不存在或者值为0则退出。

if (($DEST_UID != "") && !td_verify_ids($ids)) {  $dataBack = array("status" => 0, "content" => "-ERR " . _("接收方ID无效"));  echo json_encode(data2utf8($dataBack));+  exit();}
if (strpos($DEST_UID, ",") !== false) {}else { $DEST_UID = intval($DEST_UID);}
if ($DEST_UID == 0) { if ($UPLOAD_MODE != 2) { $dataBack = array("status" => 0, "content" => "-ERR " . _("接收方ID无效")); echo json_encode(data2utf8($dataBack)); exit(); }}

传入一个DEST_UID=2后,访问,提示无文件上传,进入文件上传逻辑。

跟进upload.php的45行,1<=count($_FILES)判断是否有文件上传,如果上传包中存在文件则直接调用52行的upload()函数,否则直接退出。

if (1 <= count($_FILES)) {  if ($UPLOAD_MODE == "1") {    if (strlen(urldecode($_FILES["ATTACHMENT"]["name"])) != strlen($_FILES["ATTACHMENT"]["name"])) {      $_FILES["ATTACHMENT"]["name"] = urldecode($_FILES["ATTACHMENT"]["name"]);    }  }
$ATTACHMENTS = upload("ATTACHMENT", $MODULE, false);
if (!is_array($ATTACHMENTS)) { $dataBack = array("status" => 0, "content" => "-ERR " . $ATTACHMENTS); echo json_encode(data2utf8($dataBack)); exit(); }
ob_end_clean(); $ATTACHMENT_ID = substr($ATTACHMENTS["ID"], 0, -1); $ATTACHMENT_NAME = substr($ATTACHMENTS["NAME"], 0, -1);
if ($TYPE == "mobile") { $ATTACHMENT_NAME = td_iconv(urldecode($ATTACHMENT_NAME), "utf-8", MYOA_CHARSET); }}else { $dataBack = array("status" => 0, "content" => "-ERR " . _("无文件上传")); echo json_encode(data2utf8($dataBack)); exit();}

跟进uoload.php第82行,判断UPLOAD_MODE参数的取值,如果没有该参数,直接返回157行的内容,回包中没有路径和后台保存的文件名。

当指定UPLOAD_MODE参数进行上传时,会回显ATTACHMENTS["ID"]和ATTACHMENTS["NAME"]两个变量拼接的字符串。ATTACHMENTS数组是52行上传文件成功upload函数返回的数组。

跟进包含在inc/utility_file.php中第1665行的upload()函数,第1692行通过is_uploadable()函数对上传文件后缀名进行检测,跟进第2307行,判断上传文件"."后面三个字符是否是php,针对Windows可以使用".php."进行绕过上传。

function is_uploadable($FILE_NAME){  $POS = strrpos($FILE_NAME, ".");
if ($POS === false) { $EXT_NAME = $FILE_NAME; } else { if (strtolower(substr($FILE_NAME, $POS + 1, 3)) == "php") { return false; }
$EXT_NAME = strtolower(substr($FILE_NAME, $POS + 1)); }

第1715行,ATTACHMENTS[ID]由add_attach()函数返回。

if ($ERROR_DESC == "") {  $ATTACH_NAME = str_replace("'", "", $ATTACH_NAME);  $ATTACH_ID = add_attach($ATTACH_FILE, $ATTACH_NAME, $MODULE);
if ($ATTACH_ID === false) { $ERROR_DESC = sprintf(_("文件[%s]上传失败"), $ATTACH_NAME); } else { $ATTACHMENTS["ID"] .= $ATTACH_ID . ","; $ATTACHMENTS["NAME"] .= $ATTACH_NAME . "*"; }

跟进add_attach()函数,1877行,上传文件保存的路径是attach目录下拼接upload.php文件中指定的$MODULE变量拼接$YM变量。

  $ATTACH_PARA_ARRAY = TD::get_cache("SYS_ATTACH_PARA");  $ATTACH_POS_ACTIVE = $ATTACH_PARA_ARRAY["SYS_ATTACH_POS_ACTIVE"];  $ATTACH_PATH_ACTIVE = $ATTACH_PARA_ARRAY["SYS_ATTACH_PATH_ACTIVE"];
if (!file_exists($SOURCE_FILE)) { return false; }
if ($MODULE == "") { $MODULE = attach_sub_dir(); }
if ($YM == "") { $YM = date("ym"); }
$PATH = $ATTACH_PATH_ACTIVE . $MODULE; if (!file_exists($PATH) || !is_dir($PATH)) { @mkdir($PATH, 448); }
$PATH = $PATH . "/" . $YM; if (!file_exists($PATH) || !is_dir($PATH)) { @mkdir($PATH, 448);  }

跟进1887行,保存的文件名

  $FILENAME = $PATH . "/" . $ATTACH_ID . "." . $ATTACH_FILE;

跟进1926行,add_attach()函数返回ATTACH_ID_NEW变量

  $ATTACH_ID_NEW = $AID . "@" . $YM . "_" . $ATTACH_ID;

至此,通过在upload.php文件指定UPLOAD_MODE变量的值为1,2,3都可以获取上传文件的路径和文件名

开发者指定的保存路径不在webroot目录下面,只能通过文件包含漏洞进行包含触发漏洞。

文件包含漏洞分析

文件包含漏洞出现在/ispirit/interface/gateway.php,首先接从客户端接收一个$json的参数,然后将$json转换为数组后再转换成变量,当存在$json数据中存在一个keyurl的且不为空的值时,并且url传入的数据中有general/或者ispirit/或者module/时,执行include_once包含该url

此处文件包含的另外一个利用,直接触发nginx的错误日志,利用文件包含直接getshell成功

包含ngnix错误日志中的php代码

漏洞修补建议

下载官方补丁:http://www.tongda2000.com/news/673.php

推荐文章++++

*国内多家企业OA系统服务器遭勒索病毒攻击


文章来源: http://mp.weixin.qq.com/s?__biz=MzAxMjE3ODU3MQ==&amp;mid=2650460286&amp;idx=2&amp;sn=33bab282bdc585b969d78d1e5aeef946&amp;chksm=83bbb59ab4cc3c8c7ad16de72e24f65192e84e7217a1860b6b7d9dc7e6c2ac3cfc827c35e112#rd
如有侵权请联系:admin#unsafe.sh