CVE-2020-10189 Zoho ManageEngine Desktop Central反序列化RCE

警告
本文最后更新于 2020-03-21,文中内容可能已过时。

跟着清水川崎师傅学习.

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

Zoho ManageEngine Desktop Central < 10.0.474

本文使用10.0.465 x64复现分析,历史版本下载移步

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

查看 DesktopCentral_Server\webapps\DesktopCentral\WEB-INF\web.xml 发现了名为 CewolfServletservlet,对应的类为 DesktopCentral_Server\lib\cewolf-1.2.4.jar 中的 de.laures.cewolf.CewolfRenderer,对应的url为/cewolf/*

image

image

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

image

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

image

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

image

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

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

web.xml中寻找上传的servlet

image

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

image

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

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

再来看对文件名的处理

image

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

image

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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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

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

image

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

image

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

image

截至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

文笔垃圾,措辞轻浮,内容浅显,操作生疏。不足之处欢迎大师傅们指点和纠正,感激不尽。