Hack The Box: Postman Write-Up

Overview
This writeup documents the methods I used to compromise the Postman machine on the Hack The Box internal Labs network. These methods include enumerating the machine with nmap, as well as enumerating the Redis service. I will also detail how I used unauthenticated access to Redis to write an arbitrary file to the target host. Finally, I will demonstrate how I leveraged a public Webmin exploit to gain a root-level shell. Postman was an Easy-rated Linux box created by jkr, worth 20 points while it was active.
This was the second HTB machine I ever completed, but I was not keeping good notes at the time, so I didn't have enough documentation to complete the write-up. I have gone back and completed the box again which is why methodology is significantly better than some of the other early boxes.
Kill Chain
Enumeration
I began this machine by using Nmap to run a full TCP port scan against the target host.
While executing Nmap, I used the -vv flag to display more verbose output, -p- to scan the entire range of potential TCP ports, -sS to use TCP SYN scanning, -T4 to set the timing template to the second fastest option, and --max-retries 0 to prevent any port scan probe retransmissions in order to help speed up the scan.
Reviewing the scan results informed me that there were four open ports detected. Nmap was guessing that an SSH service was running on tcp/22, an HTTP service on tcp/80, a redis service on tcp/6379, and a snet-sensor-mgmt service on tcp/10000.
In order to gather more information about each of these open ports and their listening services, I decided to target them with nmap service script scans. The first port I targeted was tcp/22. Since I already knew the host was up and listening, I added the -Pn flag to skip Host checks. I also added the --reason flag to have nmap report the reason a port was reported to be in a certain state, the -sV flag to probe the port to determine service/version information, -p 22 to define the single port to be scanned, and the --script flag to declare which nmap scripts should be run.
The SSH script scan results identified the service as OpenSSH running on Ubuntu. I also learned that the SSH server accepted password authentication in addition to using an SSH key.
The next scan I ran was HTTP scripts against tcp/80. I updated the -script flag to define the appropriate scripts then ran the scan.
The results of this scan confirmed that the service was an HTTP server, and specifically identified it as Apache httpd 2.4.29. The majority of the comments appeared to be comments in JS or CSS files and did not seem relevant after a quick review. I did notice that the folders /image/ and /upload/ were detected on the target host. I also noted that the internal IP address 127.0.1.1 was detected as well.
As a follow-up to the nmap scans of the HTTP server, I performed a quick review of the web page being hosted on tcp/80. As always, all interaction I performed with the site through a web browser I ensured was proxied through Burp Suite.

The page appeared to be static, and it did not appear to have any additional functionality beyond the Under Construction landing page. I also took a look at the Target Site Map in Burp Suite after running a crawl, which appeared to confirm that there were no other interesting paths at this location.

The next nmap script scans that I ran were redis scripts against tcp/6379. I updated the --script declaration and ran the scan.
The results of this scan confirmed that the redis service was listening on tcp/6379, and also informed me that the detected version was Redis 4.0.9.
Since I had an exact version number, I decided to quickly check if there were any glaring vulnerabilities for this particular service. The first place I looked for exploit information was Exploit-DB.
I opened the Redis - Replication Code Execution entry with searchsploit -x. While I did not want to use Metasploit to exploit any vulnerabilities in this box, I did want to review the code to see what the exploit was doing. The file contained a references section that included a link to this zeronights.ru PDF detailing a rogue server replication exploit. Since the PDF seemed to fairly detailed, I made a note of the link and performed a web search for redis replication rce site:github.com, which resulted in finding n0b0dyCN's redis-rogue-server repository.
I downloaded both the exploit exp.so file and the redis-rogue-server.py PoC, checked the required execution flags, then executed the PoC. While I was able to connect to the redis service and it even appeared to stage the required modules, I was unable to get an interactive or reverse shell.

Since a quick dive into the Redis service proved unfruitful, I decided to finish enumerating the last open port before dedicating any more time to enumerating Redis.
Since the initial nmap scan had reported a very vague name for the service listening on tcp/10000 I attempted to manually investigate the service banner by connecting to the port with nc.
The service banner reported back that the listening service was webmin. From experience I knew that webmin does listen on tcp/10000 by default, so attempted to connect to the resource though my browser which confirmed it.

Since I didn't care about making noise in the HTB environment, I ran an Intruder attack with Burp, but I was blocked/banned after about 4 attempts.

While investigating the body of the 403 response returned after I was blocked, I saw that the <title> tag was leaking both the Webmin version of 1.910 and the Ubuntu version of 18.04.3.

I checked Exploit-DB for any exploits matching Webmin 1.910 but found no results.
redis User Compromise
Due to the block/ban being issued on the Webmin authentication page, I deprioritized the Webmin service for the time being. I knew that this service could provide easy code execution but that it would most likely require valid access credentials to take advantage of. I also knew that without valid credentials or a private SSH key I wouldn't be able to leverage the SSH server to my advantage either. I had also deprioritized the website hosted on tcp/80 due to it being a single static page without any interactive functionality.
This left the redis service as the one I wanted to initially direct my focus on. From previous experience with redis I knew that it could contain valuable information cached in the configuration or in keys. In order to check for this type of information, and to develop an understanding of the redis environment on this machine, I connected to redis with nc and began enumerating the service using commands such as INFO. The output from INFO provided me with information such as the redis_version, OS kernel version, OS architecture, and the redis config_file location.

Next I dumped the redis config information using the command CONFIG GET *.

In this config dump I saw that the redis user SSH folder was referenced at path /var/lib/redis/.ssh. A quick web search for redis ssh resulted in finding this HackTricks section detailing how to write an arbitrary SSH key to the redis id_rsa file.
To prepare for the attack I generated a new SSH key using ssh-keygen. I used -t to specify the key type should be RSA and -f to specify the file name and path for the new key.
Next I wrote the newly generated public key to the text file postman_pub.txt.
I also had to install redis-tools using the package manager in order to get this next step to work. I had initially attempted it using nc, but the SET command was not properly executing on the redis server.
Using redis-cli, I used the SET command to write postman_pub.txt to the crackit key.
With the public key saved as a key on redis, I then connected to redis, set my working directory to /var/lib/redis/.ssh, and saved the current redis database as authorized_keys.
With the authorized_keys file written, I was then able to log in to the target host as user redis.
root User Compromise
Now that I had a foothold on the target host I began looking around manually. I saw that there was only a home path for user Matt, and the user.txt flag was located there. I also saw that SimpleHTTPPutServer.py was located in /var/www/ and was owned by user Matt, however it did not appear to be immediately useful.
I spent a few minutes listing various directory contents. Since the /opt directory is often used for programs installed independently of the package manager, I included listing it's contents in my enumeration. I was surprised to see that the only file the directory contained appeared to be an SSH key backup based on it's name of id_rsa.bak.
When I echoed out the file contents with cat I realized that the key was encrypted and would need to be cracked prior to use.
I saved the contents of id_rsa.bak locally on my Kali machine, used the ssh2john.py script to generate a hash compatible with JtR, then used John the Ripper and the rockyou.txt wordlist to crack the hash. By default you must reference the full path to the script (/usr/share/john/ssh2john.py) in Kali. Since I kept forgetting the path, I added aliases like alias ssh2john.py=/usr/share/john/ssh2john.py to my environment.
With the RSA key successfully cracked, I updated the key file permissions to 0600 then attempted to SSH in to the target host as user Matt, using the key password computer2008.
Even with the private key password I was unable to successfully authenticate as user Matt over SSH. Since I knew I had a password that had been used by user Matt before, I started thinking about where I could potentially reuse it. I remembered that I had identified the authentication portal for the webmin service earlier in my enumeration. I tested authenticating to the portal with the Matt:computer2008 credentials and was successful.

Now that I had authenticated access to webmin, I searched Exploit-DB for any relevant exploits again, using the version of 1.910 that I had detected via the 403 response to my earlier Intruder attack. The search returned two potential exploits.
I decided to begin by researching the 'Package Updates' RCE because it was an exact match to the version running on the target host. Since I didn't want to use Metasploit, I searched for webmin 1.910 rce site:github.com and found this alternative Python PoC.
In order to test for successful code execution on the host, I used tcpdump on my Kali machine to listen for icmp packets on the HTB VPN tun0 interface, then I executed exploit.py with the required variables.
With RCE confirmed, I updated the payload to an sh reverse shell, started a nc listener on tcp/443, and executed the exploit PoC again.
I checked my nc listener and saw that it had caught the reverse shell. I checked my user context and saw that I had a root shell. I was then able to dump both the root.txt flag from /root and the user.txt flag from /home/Matt.