# CVE-2020-10189 Zoho ManageEngine反序列化RCE

## 漏洞描述

在3月6日，[@steventseeley](https://twitter.com/steventseeley/status/1235635108498948096) 在twitter上发布了关于 Zoho 企业产品 Zoho ManageEngine Desktop Central 中的[反序列化](https://www.chabug.org/tags/反序列化)远程代码执行漏洞。该产品是一款基于 Web 的企业级服务器、桌面机及移动设备管理软件，可对桌面机以及移动设备管理的整个生命周期提供完全的支持，提供软件分发、补丁管理、资产管理、系统配置、远程控制、USB 外设管理、移动设备及应用管理等功能模块，帮助 IT 管理员集中远程管理大量的 PC 和 IOS/Android/Windows 移动设备。

## 影响版本

Zoho ManageEngine Desktop Central < 10.0.474

## 漏洞分析

本文使用10.0.465 x64复现分析，[历史版本下载移步](http://archives.manageengine.com/desktop-central/)。

### 寻找反序列化点

首先反序列化漏洞，肯定需要先找到反序列化的点。

查看 `DesktopCentral_ServerwebappsDesktopCentralWEB-INFweb.xml` 发现了名为 `CewolfServlet` 的`servlet`，对应的类为 `DesktopCentral_Serverlibcewolf-1.2.4.jar` 中的 `de.laures.cewolf.CewolfRenderer`，对应的url为`/cewolf/*`



[![image](resource/CVE-2020-10189%20Zoho%20ManageEngine%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96RCE/media/20200321182965.png)](https://y4er.com/img/uploads/20200321182965.png)





[![image](resource/CVE-2020-10189%20Zoho%20ManageEngine%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96RCE/media/20200321185502.png)](https://www.chabug.org/wp-content/uploads/2020/04/20200321185502.png)



`CewolfRenderer` 类继承 `HttpServlet` 是一个 `servlet`，在其 `doGet` 方法中



[![image](resource/CVE-2020-10189%20Zoho%20ManageEngine%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96RCE/media/20200321182003.png)](https://www.chabug.org/wp-content/uploads/2020/04/20200321182003.png)



`imgKey` 可控，然后调用 `storage.getChartImage(imgKey, request)` 。`Storage` 类是一个接口，在这个jar包中，`FileStorage` 类实现了 `Storage` 接口的 `getChartImage` 方法。



[![image](resource/CVE-2020-10189%20Zoho%20ManageEngine%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96RCE/media/20200321181041.png)](https://www.chabug.org/wp-content/uploads/2020/04/20200321181041.png)



很明显的看到直接将之前传入的 `img` 当作 `imgKey` 参数，然后通过 `getFileName()` 获取文件名然后进行 `ObjectInputStream` 的 `readObject()`，再看 `getFileName()`。



[![image](resource/CVE-2020-10189%20Zoho%20ManageEngine%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96RCE/media/20200321183565.png)](https://www.chabug.org/wp-content/uploads/2020/04/20200321183565.png)



进行了一个简单的拼接，无伤大雅。

捋一下，通过img传入参数触发读文件进而反序列化，现在的问题就是这个恶意的序列化文件我们怎么传上去，并且路径要有`_chart`。

### 寻找上传点

web.xml中寻找上传的servlet



[![image](resource/CVE-2020-10189%20Zoho%20ManageEngine%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96RCE/media/20200321186974.png)](https://www.chabug.org/wp-content/uploads/2020/04/20200321186974.png)



跟进之后发现udid、filename可控，并且udid被拼接到文件保存目录中。



[![image](resource/CVE-2020-10189%20Zoho%20ManageEngine%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96RCE/media/20200321185491.png)](https://www.chabug.org/wp-content/uploads/2020/04/20200321185491.png)



```java
String localDirToStore = baseDir + File.separator + "mdm-logs" + File.separator + this.customerID + File.separator + this.deviceName + "_" + udid;
```



那么我们可以跨目录上传，在上文中我们传入文件名触发反序列化时会拼接 `this.basePath + "_chart" + id` 到路径中，所以我们需要构造一个 `_chart` 的路径 `aaa......webappsDesktopCentral_chart`。

再来看对文件名的处理



[![image](resource/CVE-2020-10189%20Zoho%20ManageEngine%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96RCE/media/20200321186665.png)](https://www.chabug.org/wp-content/uploads/2020/04/20200321186665.png)



然后文件名转小写之后进行了 `FileUploadUtil.hasVulnerabilityInFileName(fileName, "log|txt|zip|7z")` 的校验，然后拼接为完整的文件路径，看下校验了什么。



[![image](resource/CVE-2020-10189%20Zoho%20ManageEngine%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96RCE/media/20200321184618.png)](https://www.chabug.org/wp-content/uploads/2020/04/20200321184618.png)



然后进行 `isContainDirectoryTraversal()` 、 `isCompletePath()` 、 `isValidFileExtension()` 的校验。

```java
private static boolean isContainDirectoryTraversal(String fileName) {
    return fileName.contains("/") || fileName.contains("\");
}

private static boolean isCompletePath(String fileName) {
    String regexFileExtensionPattern = "([a-zA-Z]:[\ \\ / //].*)";
    Pattern pattern = Pattern.compile(regexFileExtensionPattern);
    Matcher matcher = pattern.matcher(fileName);
    return matcher.matches();
}

private static boolean isContainExecutableFileExt(String fileName) {
    if (fileName.indexOf("u0000") != -1) {
        fileName = fileName.substring(0, fileName.indexOf("u0000"));
    }

    String fileExtension = FilenameUtils.getExtension(fileName).trim();
    if (!fileExtension.trim().equals("")) {
        fileExtension = fileExtension.toLowerCase();
        ArrayList executableFileExts = new ArrayList(Arrays.asList("jsp", "js", "html", "htm", "shtml", "shtm", "hta", "asp"));
        if (executableFileExts.contains(fileExtension)) {
            return true;
        }
    }

    return false;
}
```



判断是否文件名进行了目录穿越、是否是合法后缀等，但是因为之前的目录是由udid控制的，并不影响我们的文件上传。而在web.xml中引入了security-mdm-agent.xml



[![image](resource/CVE-2020-10189%20Zoho%20ManageEngine%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96RCE/media/20200321187536.png)](https://www.chabug.org/wp-content/uploads/2020/04/20200321187536.png)



在 `security-mdm-agent.xml` 中有一个校验，只允许文件名为 `logger.txt|logger.zip|mdmlogs.zip|managedprofile_mdmlogs.zip`



[![image](resource/CVE-2020-10189%20Zoho%20ManageEngine%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96RCE/media/20200321183022.png)](https://www.chabug.org/wp-content/uploads/2020/04/20200321183022.png)



所以构造如下请求，即可上传文件



[![image](resource/CVE-2020-10189%20Zoho%20ManageEngine%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96RCE/media/20200321181636.png)](https://www.chabug.org/wp-content/uploads/2020/04/20200321181636.png)



### 寻找gadgets

`DesktopCentral_Serverlib` 中有 `commons-collections.jar(3.1)`、`commons-beanutils-1.8.0.jar`，完美。使用ysoserial生成序列化文件，先上传然后触发反序列化就完事了。注意ysoserial的pom.xml要和目标的jar版本一样。



[![image](resource/CVE-2020-10189%20Zoho%20ManageEngine%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96RCE/media/20200321181885.png)](https://www.chabug.org/wp-content/uploads/2020/04/20200321181885.png)



## 漏洞修复

截至2020/03/20 9.34分，官网版本为10.0.515，已经修复了漏洞，请更新。

## 参考链接

1. https://srcincite.io/pocs/src-2020-0011.py.txt
2. https://www.anquanke.com/post/id/200474
3. https://www.manageengine.com/products/desktop-central/remote-code-execution-vulnerability.html