/var/log $ cat "Hack The Box - Fortune Walkthrough"
2019-08-03 | hackthebox ctf
- Find and use RCE on port 80 website.
- Get the Intermediate CA private key and create a client certificate for accessing HTTPS.
- Get a SSH key from the HTTPS website.
- SSH into box and re-scan the box to discover a NFS share.
- Mount the share to get user flag and hint for root password.
- Reverse engineer how pgAdmin 4 v3.4 decrypts passwords.
- Decrypt the database password to gain root access.
nmap scan report we can see three TCP services running: SSH, HTTP and HTTPS. From the HTTP header we can see that the box is presumably running OpenBSD where
httpd is the OpenBSD web server.
SSH and HTTPS
As normally SSH is not the way forward in the first place I skipped having a look at it.
When trying to access
https://10.10.10.127 after accepting the self-signed certificate we get a
Accessing the URL with
curl gives us some more details what happened:
Checking against the TLSv1.2 specification in The Transport Layer Security (TLS) Protocol Version 1.2 - 7.4 Handshake Protocol wee see that the server requests a client certificate from us. As we do not have one we cannot access HTTPS for now.
http://10.10.127 we get a very simple site where we can select a fortune database and when hitting submit outputs a random fortune for us:
From the code of the page or using
burp we can see what is posted to the
burp’s intruder module in sniper mode with the All-attack.txt word-list from
wfuzz outputs something quite useful:
Using the repeater function to confirm that we do have RCE here:
Getting a Shell (sort of)
Despite the box having a few tools which would allow a reverse shell I could not get one working. So I wrote a little Python script which uses the RCE to have a pseudo shell:
Checking httpd.conf found in
/etc/httpd.conf we see which CA certificate is used for the client authentication:
Searching through the box we also can find a private key in
Judging based on the file path this seems to be an intermediate CA private key. After copying both the private key and the CA certificate from
/etc/ssl/ca-chain.crt over to our own machine and using this guide we can confirm that the key we found was used so sign the CA certificate used for the TLS client authentication:
Now we create our own client certificate and convert it:
After importing our newly created PKCS12 certificate into our browser we are now able to access HTTPS:
Hitting ‘generate’ we are presented with a SSH key pair:
SSH and more Services
After copy-pasting the private key from the website we try to ssh into the box. As the page does not give us any clue which username to use we have to figure it out. From
/etc/passwd we know the users ‘bob’, ‘charlie’ and ’nfsuser’. Trying them we find that ’nfsuser’ works but the shell is not working in any way:
nmap again while connected to SSH we find some more services now:
Having a look what NFS shares are available and mounting it we can grab the user flag found in
Full SSH Access
To get a fully interactive SSH session we add ourself to
/home/charlie/.ssh/authorized_keys using either the key pair which was generated on the website or with a new pair. Now we have SSH access as ‘charlie’:
/home/charlie we find the file
mbox which gives us a very helpful hint:
Obtaining the ‘dba’ Password
From the pgAdmin 4 3.4 documentation we can see that the configuration parameters are stored in a file named
config_local.py. Searching for it and having a look in its contents we can determine the path to the SQLite database where pgAdmin stores credentials:
Using the SQLite client installed on the box we can get the encrypted password from the table ‘server’:
Decrypting the Password and getting the Flag
After installing and running pgAdmin 4 version 3.4 in a local test environment we find that the password crypto part is handled in the module
crypto.py. As it turns out all we need to decrypt the ‘dba’ password is the hashed user password (no need to know it what it is) from the user who did the database setup.
Again we use the SQLite to get the user password hashes from the table ‘user’:
Next step is to modify
crypto.py so that it decrypts the password for us:
The decryption using the hash of ‘charlie’ does not look promising whereas the version with bob’s hash does:
su with ‘R3us3-0f-a-P4ssw0rdl1k3th1s?_B4D.ID3A!’ as root password works and we can grab the flag: