Hack The Box — Interpreter (Linux) Write-Up: CVE-2023-43208 Mirth Connect RCE → double f-string eval() PrivEsc
TL;DR
On Interpreter, initial access is obtained by exploiting an unauthenticated XStream deserialization vulnerability (CVE-2023-43208) in NextGen Mirth Connect 4.4.0, yielding a shell as user mirth. Post-exploitation database queries allow us to retrieve a hash for user sedric, which is cracked (PBKDF2-HMAC-SHA256) to gain SSH access. Privilege escalation is achieved by exploiting a double-evaluation f-string vulnerability in a local Flask application running as root.
Target
- Host:
interpreter.htb - IP:
10.129.16.252
Recon: Open ports and Mirth Connect discovery
An initial network scan reveals:
- Port 22/tcp: SSH
- Port 80/443/tcp: HTTP/HTTPS hosting NextGen Mirth Connect Administrator
- Port 6661/tcp: Mirth Connect internal communications
Analyzing the JNLP file from the web administrator portal confirms the version is NextGen Mirth Connect 4.4.0, which is vulnerable to unauthenticated XML deserialization.
Initial Foothold: XStream Deserialization (CVE-2023-43208)
The version of Mirth Connect is vulnerable to CVE-2023-43208, a bypass of the XStream deserialization fix. The endpoint accepts raw XML payloads without authentication.
Using XStream deserialization gadget chains, we trigger a shell execution that connects back to our listener. We obtain a shell as user mirth.
User Access: Database extraction & PBKDF2 hash cracking
We investigate the application properties at /usr/local/mirthconnect/conf/mirth.properties. We retrieve the database credentials for MariaDB: MirthPass123!.
Connecting to the database, we query the PERSON table and extract the hash for the user sedric. The hash is stretched using PBKDF2-HMAC-SHA256 with 600,000 iterations. We crack the hash using John/Hashcat to reveal the password: snowflake1. We connect via SSH as sedric.
Privilege Escalation: Python f-string Double Evaluation
Local enumeration reveals a Flask application running as root on local port 54321: /usr/local/bin/notif.py. It parses incoming patient records and evaluates them dynamically using double f-string formatting inside eval():
template = f"Patient {first} {last} ({gender}), {{datetime.now().year - year_of_birth}} years old"
try:
return eval(f"f'''{template}'''")Because of this double evaluation, wrapping Python code inside curly braces {} triggers execution. The script enforces a regex to restrict characters, blocking spaces and semi-colons.
We bypass this filter by base64-encoding our command and invoking it via __import__("os").popen():
# Payload
{__import__("os").popen(__import__("base64").b64decode("aW5zdGFsbCAtbyByb290IC1tIDQ3NTUgL2Jpbi9iYXNoIC90bXAvLnNo").decode()).read()}We send the XML payload to local port 54321, spawning a SUID root bash shell at /tmp/.sh. We run it to obtain root access.
Defensive notes / remediation
Fix
- Upgrade NextGen Mirth Connect to a patched version (4.4.1+).
- Do not use
eval()with f-strings to format strings containing user input. - Avoid exposing critical administrative services on loopback ports without authentication.
Monitoring / detection ideas
- Monitor XML payloads for XStream signature gadgets (like
java.lang.ProcessBuilder). - Watch for executions of SUID binaries spawned in temporary folders.
Lessons learned
- Secure password hashing (PBKDF2 with high iterations) is still vulnerable if weak passwords are used.
- Python
eval()combined with dynamic formatting leads to trivial command injection.
Appendix: Timeline summary
- Recon -> Identify exposed Mirth Connect 4.4.0.
- Foothold -> Execute exploit for CVE-2023-43208 to get shell as
mirth. - User -> Dump MariaDB database, crack PBKDF2 hash, SSH as
sedric. - Privilege Escalation -> Leverage f-string double evaluation on port 54321 to get root.