HTB: Keeper
Request Tracker default creds to reused SSH password, then a KeePass dump CVE recovers the root PuTTY key
A ticketing subdomain ran Request Tracker with default root:password. A ticket exposed lnorgaard's password, which was reused for SSH. Her home held a KeePass database and a memory dump, and CVE-2023-32784 recovered the master password from the dump. The database stored root's PuTTY private key, which converted to an OpenSSH key for a root login.
the box
Keeper is an easy Linux box and it plays like a real helpdesk does. A ticketing portal on the front, a sloppy admin who pasted a default password into a user comment, and a KeePass database left next to its own crash dump. Two credential mistakes from end to end, but the root half leans on a memory-disclosure CVE that is worth doing by hand.
Target was 10.10.11.227.
recon
I started with a full TCP sweep, then ran scripts and version detection against the open ports.
nmap -p- --min-rate 10000 10.10.11.227
nmap -p 22,80 -sCV 10.10.11.227
Two ports answered:
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.3 (Ubuntu Linux; protocol 2.0)
80/tcp open http nginx 1.18.0 (Ubuntu)
| http-methods:
|_ Supported Methods: GET HEAD
|_http-server-header: nginx/1.18.0 (Ubuntu)
|_http-title: Site doesn't have a title (text/html).
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
OpenSSH 8.9p1 puts the host on Ubuntu 22.04. nginx 1.18.0 is the stock package. Nothing else, so the web port is the whole attack surface.
The site at http://10.10.11.227/ had no title and almost no content. The body was a single link:
<a href="http://tickets.keeper.htb/rt/">To raise an IT support ticket, please visit tickets.keeper.htb/rt/</a>
So the app expects name-based virtual hosting, and it leaks the hostnames itself. I added both to /etc/hosts:
10.10.11.227 keeper.htb tickets.keeper.htb
For completeness I also confirmed the subdomain with a vhost fuzz, which is how I would have found it without the index hint:
gobuster vhost -w subs.txt -u keeper.htb
[+] Url: http://keeper.htb
[+] Method: GET
[+] Threads: 10
Found: tickets.keeper.htb (Status: 200) [Size: 4236]
foothold
http://tickets.keeper.htb/rt/ served a login page for Request Tracker, the Best Practical ticketing system. The footer gave the exact version:
RT 4.4.4+dfsg-2ubuntu1
RT ships with a well-known install-time superuser, root:password, and the docs nag you to change it on first boot. Here nobody did. I logged straight into the admin panel:
username: root
password: password
That is the foothold. No exploit, just an unchanged default on a production ticketing system.
user
Inside RT I went to the admin user list at Admin > Users. Two accounts existed:
27 lnorgaard Lise Nørgaard lnorgaard@keeper.htb Enabled
14 root Enoch Root root@localhost Enabled
I opened lnorgaard’s user record at Admin > Users > lnorgaard. The admin edit page shows every field on the account, and whoever provisioned her had typed her starter password straight into the Comments box on the profile. It sat there in cleartext:
New user. Initial password set to Welcome2023!
There was also a ticket on the box describing a KeePass crash. lnorgaard had been troubleshooting KeePass and was instructed to attach a process dump, which is the breadcrumb that the root path is going to involve a KeePass memory dump. Hold that thought.
Password reuse did the rest. Welcome2023! worked for SSH:
ssh lnorgaard@keeper.htb # Welcome2023!
lnorgaard owned user.txt. Her home directory also held RT30000.zip, an 84MB archive tied to the KeePass ticket. I pulled it down and unpacked it:
scp lnorgaard@keeper.htb:/home/lnorgaard/RT30000.zip .
unzip RT30000.zip
It contained exactly the pair you want for the next CVE:
KeePassDumpFull.dmp # ~242MB process memory dump
passcodes.kdbx # 3.6K KeePass 2.x database
root
A KeePass crash dump sitting next to its .kdbx is the signature of CVE-2023-32784. KeePass 2.x before 2.54 builds the master password in a custom SecureTextBoxEx control, and for every character typed it leaves a managed string •a, ••b, •••c and so on in the heap. That residue survives into a process dump. The first character never lands as a recoverable string, but every character after it can be carved out, so you recover the password minus its first byte and guess the leading character.
I used the keepass-password-dumper carving tool against the dump. The .NET reference implementation is the original PoC:
dotnet run KeePassDumpFull.dmp
It printed one candidate per position, with the unknown first character as a set of options:
Found: ●{ø, Ï, ,, l, `, -, ', ], §, A, I, :, =, _, c, M}dgrød med fløde
So the tail was dgrød med fløde and the first character was one of the listed bytes. The phrase is Danish (Lise Nørgaard is a Danish author, the box leans into it), and rødgrød med fløde is a classic Danish dish and pronunciation test. The master password:
rødgrød med fløde
There is also a pure-Python carver in the same family if you would rather not pull in the .NET runtime, it reads the same heap pattern out of the dump.
I copied the database off the box and opened it locally. Either a GUI or the CLI works. With kpcli:
scp lnorgaard@keeper.htb:/home/lnorgaard/passcodes.kdbx .
kpcli --kdb passcodes.kdbx
# master password: rødgrød med fløde
Listing entries, the database held a keeper.htb (Ticketing Server) entry whose Notes field carried root’s SSH access not as a passphrase but as a full PuTTY private key (.ppk). The entry also pasted the public key and the raw RSA parameters. I saved the PuTTY key out as keeper.txt:
PuTTY-User-Key-File-3: ssh-rsa
Encryption: none
Comment: rsa-key-20230519
Public-Lines: 6
AAAAB3NzaC1yc2EAAAADAQABAAABAQCnVqse/hMswGBRQsPsC/EwyxJvc8Wpul/D
...
OpenSSH cannot consume a .ppk directly, so I converted it to an OpenSSH private key with puttygen from the putty-tools package:
puttygen keeper.txt -O private-openssh -o id_rsa
chmod 600 id_rsa
ssh root@keeper.htb -i id_rsa
That logged in as root and handed over root.txt.
takeaway
Both ends of this box are credential hygiene failures. A production ticketing system left on its install-time root:password is an instant admin login, and dropping a starter password into a user-profile comment, then reusing it for SSH, turns a web account into a shell. The root step is the interesting one. CVE-2023-32784 is a reminder that a secret manager leaks through process memory, and that the residue of a custom text box is enough to rebuild a master password from a crash dump. Storing a private key inside a vault is only ever as safe as the vault’s master password, and that one was a Danish tongue-twister sitting in a dump in the user’s home.