Bolt is a medium rated machine on HackTheBox created by d4rkpayl0ad & TheCyberGeek. For the user part we will fuzz multiple vhosts and analyze source code to find a SSTI vulnerability which leads to RCE and a reverse shell. On the machine we find that the database credentials are reused for the user eddie. Eddie’s chrome log reveals a GPG private key which we can use to decrypt a passbolt secret which contains the root users password.
User
Nmap
As usual we begin our enumeration with a nmap scan against all ports followed by a script and version detection scan against the open ones to get an initial overview of the attack surface.
All ports
1 |
|
Script and version
1 |
|
SSTI
The nmap scan already discovered a vhost in passbolt.bolt.htb
on https, so we add it and bolt.htb
to our /etc/hosts
file. Using fuff on port 80 we can discover mail.bolt.htb
and demo.bolt.htb
which we also add to our /etc/hosts
file.
1 |
|
Checking all the pages manually in our browser bolt.htb
seems to be the homepage of a web development company.
passbolt.bolt.htb
looks like an installation of passbolt, a password management solution for teams.
mail.bolt.htb
seems to be an installation of roundcube, a webmail software.
Going over to demo.bolt.htb
we can log in or register a new user.
Let’s first inspect the main page http://bolt.htb
. Going over to Download
we can download a docker image.
Downloading and extracting it, the image contains multiple layers.
1 |
|
We can extract all the tar archives in the respective folders using the find
command.
1 |
|
Checking for which page which source code is used we go over to demo.bolt.htb
where we can register a new user specifying an invite code.
Intercepting the request with burp we see the parameter for the invite code in the request is invite_code
.
Knowing the parameter we can now cross reference the source for it using grep
. It seems to be used in a routes.py
file of a flask application.
1 |
|
Taking a closer look at routes.py
the expected parameter for invite_code
is hardcoded to XNSS-HSJW-3NGU-8XTJ
.
41093412e0da959c80875bb0db640c1302d5bcdffec759a3a5670950272789ad/app/home/routes.py
1 |
|
Using this key we are now able to create our own user.
Being logged in we are now in an AdminLTE 3 dashboard.
The newly created account lets us also log into the roundcube web mail application.
To find the source of underlying functionality we take a unique looking string again and cross reference it with the source code.
This seems to be used in the examples-profile.html
which is used in the routes.py
of the home
app.
1 |
|
1 |
|
There we can see the full source code of the application.
41093412e0da959c80875bb0db640c1302d5bcdffec759a3a5670950272789ad/app/home/routes.py
1 |
|
The interesting part is that the application sends a confirmation email. Upon clicking on the confirmation link it sends another confirmation mail stating the change took place. For this it renders the template update-name.html
with the new username directly passed to the templating engine making it vulnerable to SSTI.
1 |
|
41093412e0da959c80875bb0db640c1302d5bcdffec759a3a5670950272789ad/app/home/templates/emails/update-name.html
1 |
|
To confirm our suspicion we first set our username to {{config.items()}}
in the settings of the AdminLTE3 dashboard.
Clicking submit we get sent a confirmation mail to roundcube.
Following the confirmation link we get sent another confirmation that the change took place and see our injection for the username got executed.
The next step is to get a reverse shell. We exchange our username to a SSTI payload that will curl our webserver and pass index.html
over to sh
.
We create a small bash reverse shell as our index.html
and serve it with a python web server.
index.html
1 |
|
1 |
|
Next we set up a ncat listener to catch the reverse shell.
1 |
|
We submit the name change request and upon clicking the confirmation link in roundcube our reverse shell get’s downloaded from the web server and we get a connection back on our listener.
1 |
|
We upgrade the shell using python and also fix the terminal size for better access.
1 |
|
Config
Looking around we can find the configuration for passbolt which reveals database credentials.
1 |
|
Checking for users on the machine we find the /home
directory folders for clark and eddie.
1 |
|
Trying the found password for eddie over ssh it works and we are able to grab the user flag.
1 |
|
Root
GPG
Running linpeas reveals some possible ssh keys.
1 |
|
Taking a closer look at the google chrom logfile we find a GPG private key which we first need to clean a bit to use it.
1 |
|
key.gpg
1 |
|
The key is protected with a passphrase but we can use gpg2john
and john
to crack it quickly.
1 |
|
1 |
|
Manually
There there were different methods to use this key to the decrypt the secret stored in passbolt. One was to retrieve the pgp message from the database.
1 |
|
1 |
|
1 |
|
We save the message to message.enc
and import the private key into gpg.
1 |
|
Now we can decrypt the message.
1 |
|
This reveals a password which let’s us switch to the root user and read the flag.
1 |
|
1 |
|
Passbolt
Another method was to use passbolt following this forum post. We first use the email for eddie on the passbolt application.
Then we connect to the database with the earlier found password and retrieve the needed user id and authentication token to reset access to passbolt.
1 |
|
1 |
|
To use passbolt we first have to install the browser extension.
Now we can import the GPG private key for eddie and specify the passphrase we retrieved with john.
Now we have to select 3 random letters and a color as additional security requirement.
Being logged into passbolt as eddie we can now retrieve the root password using the passphrase, switch to the root user and add the flag to our collection.
1 |
|