Vamos a realizar un segundo escaneo para obtener más detalle de ambos puertos:
Vemos que en el 8080no obtenemos gran información solo que se está empleando un proxy para hacer pública la web.
Vamos a ver la aplicación web:
Vemos que tenemos una zona para poner texto donde Ask a question vamos a poner cualquier cosa:
Vemos que nos responde lo que podría ser un ChatBot. Vamos a ver como se tramita por detrás esto:
Vemos que apunta a un endpoint llamado ask donde le pasa el parámetro query con nuestro input como valor, la respuesta del servidor es el siguiente contenido en JSON:
Vemos que si ponemos otro tipo de input devuelve:
Vemos que se trata de una serie de respuestas ya configuradas, si probamos otro tipo de inputs recibiremos como respuesta la misma respuesta. En este caso el ChatBot esta en mantenimiento y ni disponible para responder otro tipo de preguntas. Así que no podremos jugar con algún Prompt Injection. Vamos a realizar fuzzing para ver si hay algo interesante en la web:
En esta parte es un poco rara, ya que el directorio que nos interesa devuelve un 404 y no sale en el fuzzing normal. Cuando lo hagaís vereis muchos endpoints que son del ChatBot.
Podemos ver el endpoint static si accedemos a el veremos lo siguiente:
Shell as raton
Vemos que está devolviendo un error ya que está intentando apuntar a un archivo que no encuentra, vamos a intentar un Path Traversal:
Vemos que funciona, vamos a ver que usuarios existen en el sistema:
Vemos que existen los siguientes usuarios
vboxuser
raton
churrumais
Vamos a intentar leer el id_rsa de todos los usuarios:
vboxuser:
raton:
Podemos leer el id_rsa vamos a darle los respectivos permisos al archivo e intentar acceder por SSH:
Vemos que la id_rsa no esta siendo aceptada y transcurre al método de contraseña... Así que vamos aprovechar el Path Traversal para leer las variables de entorno, para ello apuntaremos a /proc/self/environ que nos permitirá leer las variables de entorno del propietario del proceso.
Comparto un esquema visual de lo que estaría ocurriendo:
La zona vulnerable al LFI es causada por esta parte del código:
path.lstrip('/') lo que hace quitar todas las / en el inicio. Así que si nuestro input que metemos es /etc/passwd esto lo dejará como etc/passwd .
Aquí define directorios permitidos para que la aplicación las considere válidas. APP_ROOT normalmente suele ser la ruta en donde se encuentra alojada el servidor como por ejemplo /var/www/html/ . Luego con os.path.join une la ruta completa alojada la web añadiendo site y wwwroot entonces lo dejaría algo como /var/www/html/site/wwwroot/ . Luego vemos que recoge el valor de la variable de entorno HOME en este caso si el usuario raton es el que está desplegando la aplicación el valor que obtiene es /home/raton/ .
Así que vamos a leer las variables de entorno:
Si vemos las variables podemos encontrar la variable llamada SNOWFLAKE_PASSWORD donde nos da una contraseña que es ratonguaton . Vamos a probarlas para acceder por SSH:
Ya estamos dentro como el usuario raton !!
Si hacemos un ls podremos ver lo siguiente:
Vemos que la aplicación web era NLWeb . Si entramos y leemos el requeriments.txt encontraremos lo siguiente:
Vemos que emplea aiohttp>=3.9.1 con la vulnerabililad de Path Traversal reportada e identificada como CVE-2024-23334.
Shell as root
Vamos a ver los puertos abiertos en la máquina:
Vemos que está el puerto 5000 abierto, vamos a lanzar un curl para ver que se trata:
Vemos que se trata de un login, vamos a hacer Port Forwarding para llevarnos el puerto a nuestra máquina. Para ello lo haré con SSH:
Ahora vamos a intentar acceder a la aplicación web:
Vamos a probar algunas credenciales predeterminadas como admin:admin :
Vemos que solo puede acceder el usuario churrumais cuyo usuario existente en el sistema desconocemos de sus credenciales. Buscando por el sistema encontré lo siguiente en el /opt/ :
Vemos la aplicación web loganalyzer vamos a leer su código:
Vemos que se trata de una aplicación en Flask. Donde podemos ver lo siguiente definido:
Ya tenemos las credenciales de acceso como churrumais vamos a probarlas:
Vamos a darle a Go to Log Analysis a ver que ocurre:
Vemos que podemos ejecutar algún comando 👀... Vamos a probar id :
No ocurrió nada, vamos a ver que ocurre por atrás:
Vemos que se tramita por POST, ya que tenemos el código fuente vamos a ver que hace con nuestro input:
Vemos que pilla y guarda nuestro input en la variable filter_cmd donde luego lo mete y ejecuta en grep -r '{filter_cmd}' /var/log/analyzer/ 2>/dev/null . Así que viendo donde se guarda nuestro input donde lo mete entre comillas simples podremos cerrarlas añadir un nuevo comando y comentar todo lo demás. Así que el payload podría quedar algo así:
Vamos a ver si se ha creado el archivo y con que usuario:
Lo crea como root , vamos a darle SUID a /bin/bash :
┌──(pylon㉿kali)-[~/…/THL/Cuento/content/raton]
└─$ ssh -i id_rsa raton@192.168.3.129
** WARNING: connection is not using a post-quantum key exchange algorithm.
** This session may be vulnerable to "store now, decrypt later" attacks.
** The server may need to be upgraded. See https://openssh.com/pq.html
raton@192.168.3.129's password:
┌──(pylon㉿kali)-[~/…/THL/Cuento/content/raton]
└─$ ssh -i id_rsa raton@192.168.3.129
** WARNING: connection is not using a post-quantum key exchange algorithm.
** This session may be vulnerable to "store now, decrypt later" attacks.
** The server may need to be upgraded. See https://openssh.com/pq.html
raton@192.168.3.129's password:
Welcome to Ubuntu 20.04.6 LTS (GNU/Linux 5.15.0-139-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
* Introducing Expanded Security Maintenance for Applications.
Receive updates to over 25,000 software packages with your
Ubuntu Pro subscription. Free for personal use.
https://ubuntu.com/pro
Expanded Security Maintenance for Infrastructure is not enabled.
0 updates can be applied immediately.
Enable ESM Infra 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
Your Hardware Enablement Stack (HWE) is supported until April 2025.
Last login: Tue Dec 9 12:17:47 2025 from 192.168.1.20
raton@cuentos:~$
raton@cuentos:~$ ls
Desktop Documents Downloads NLWeb users.txt
raton@cuentos:~$ curl 127.0.0.1:5000
<!doctype html>
<html lang=en>
<title>Redirecting...</title>
<h1>Redirecting...</h1>
<p>You should be redirected automatically to the target URL: <a href="/login?next=%2F">/login?next=%2F</a>. If not, click the link.
┌──(pylon㉿kali)-[~/…/THL/Cuento/content/raton]
└─$ ssh -L 127.0.0.1:5000:127.0.0.1:5000 -i id_rsa raton@192.168.3.129
** WARNING: connection is not using a post-quantum key exchange algorithm.
** This session may be vulnerable to "store now, decrypt later" attacks.
** The server may need to be upgraded. See https://openssh.com/pq.html
raton@192.168.3.129's password:
Welcome to Ubuntu 20.04.6 LTS (GNU/Linux 5.15.0-139-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
* Introducing Expanded Security Maintenance for Applications.
Receive updates to over 25,000 software packages with your
Ubuntu Pro subscription. Free for personal use.
https://ubuntu.com/pro
Expanded Security Maintenance for Infrastructure is not enabled.
0 updates can be applied immediately.
Enable ESM Infra 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
New release '22.04.5 LTS' available.
Run 'do-release-upgrade' to upgrade to it.
Your Hardware Enablement Stack (HWE) is supported until April 2025.
Last login: Thu Dec 25 10:17:52 2025 from 192.168.3.128
raton@cuentos:~$
raton@cuentos:~$ ls /opt/
loganalyzer scripts
raton@cuentos:/opt/loganalyzer$ ls
app.py templates
from flask import Flask, request, render_template, redirect, url_for, flash
from flask_login import LoginManager, UserMixin, login_user, login_required, logout_user, current_user
import os
app = Flask(__name__)
app.secret_key = 'clave-secreta-para-sesiones-churrumais-2025'
login_manager = LoginManager()
login_manager.init_app(app)
login_manager.login_view = 'login'
USUARIO = {'username': 'churrumais', 'password': 'VillaeEla13'}
class User(UserMixin):
def __init__(self, id):
self.id = id
@login_manager.user_loader
def load_user(user_id):
return User(user_id) if user_id == USUARIO['username'] else None
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
username = request.form['username']
password = request.form['password']
if username == USUARIO['username'] and password == USUARIO['password']:
user = User(username)
login_user(user)
return redirect(url_for('dashboard'))
else:
flash('Invalid credentials. Access is restricted to the user churrumais.', 'danger')
return render_template('login.html')
@app.route('/logout')
@login_required
def logout():
logout_user()
return redirect(url_for('login'))
@app.route('/')
@login_required
def index():
return redirect(url_for('dashboard'))
@app.route('/dashboard')
@login_required
def dashboard():
return render_template('dashboard.html', username=current_user.id)
@app.route('/search_logs', methods=['GET', 'POST'])
@login_required
def search_logs():
results = None
if request.method == 'POST':
filter_cmd = request.form['filter']
try:
output = os.popen(f"grep -r '{filter_cmd}' /var/log/analyzer/ 2>/dev/null").read()
results = output
except:
results = "Error al ejecutar el comando."
return render_template('search.html', results=results, username=current_user.id)
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000, debug=True)