La inyección XML es la manipulación de la entrada XML para alterar la forma en que una aplicación analiza o interpreta los datos. Se produce cuando una entrada controlada por el usuario se inserta en un documento XML sin la validación adecuada, lo que permite a los agresores inyectar nodos, atributos, entidades o cargas útiles que modifican el flujo de control, eluden la lógica o activan comportamientos peligrosos del analizador. En los actuales ecosistemas basados en la integración y con gran cantidad de API, la inyección de XML sigue siendo una amenaza real que los equipos de seguridad no pueden ignorar.
A diferencia de la simple manipulación de entradas, la inyección XML explota el poder expresivo del propio XML, afectando a sistemas complejos como SOAP, SAML, dispositivos IoT, integraciones empresariales y sistemas financieros heredados.
Por qué sigue siendo importante la inyección XML
Aunque JSON domina las aplicaciones modernas, XML está profundamente arraigado en el software empresarial, los protocolos de autenticación y las integraciones backend. Los atacantes pueden abusar de las estructuras XML para:
- Manipular la lógica empresarial
- Inyectar nodos no autorizados
- Manipular consultas XPath
- Desencadenar la divulgación de archivos al estilo XXE
- Interrupción de la validación del esquema
- Provocar una denegación de servicio basada en XML
La flexibilidad de XML hace que su uso indebido sea especialmente poderoso.
Ejemplo real de CVE: CVE-2025-13526
CVE-2025-13526 demuestra cómo un simple error de configuración de análisis XML puede conducir a la divulgación completa de archivos. El sistema permitía cargar archivos de configuración XML, pero no desactivaba la resolución de entidades externas.
Ejemplo de carga maliciosa:
xml
<!DOCTYPE datos [
]>
&xxe;
El servidor devolvió el contenido de /etc/passwdmostrando cómo la inyección XML combinada con XXE puede exponer archivos críticos.
Superficies de ataque de la inyección XML
Los atacantes abusan:
- Inyección de nodos
- Inyección de atributos
- Manipulación de consultas XPath
- Manipulación de esquemas (XSD)
- Cargas útiles XXE
- Ampliación de entidades para DoS
- Derivación lógica dentro de flujos de trabajo basados en XML
Cada categoría afecta a una capa diferente del sistema.
Ejemplos de ataque (se conserva la misma cantidad)
- Manipulación de la inyección de nodos
xml
ProductoA
Carga útil inyectada:
pgsql
verdadero.
El XML resultante se corrompe estructuralmente y puede conceder privilegios no autorizados.
Inyección XPath
python
query = f"//usuarios/usuario[nombredeusuario/text()='{usuario}']"
Entrada maliciosa:
bash
o "1"="1
Esto deja al descubierto registros de usuarios no autorizados.
XXE Carga útil
xml
<!DOCTYPE foo [
]>&payload;
Manipulación de esquemas
xml
<xs:element name="amount" type="xs:string"/>
Esto desactiva el comportamiento de validación esperado.
Mil millones de risas DoS
xml
<!ENTITY a "ha"><!ENTITY b "&a;&a;"><!ENTITY c "&b;&b;">
La expansión masiva sobrecarga el analizador sintáctico.
Técnicas defensivas
Desactivar la resolución de entidades
python
parser = etree.XMLParser(resolve_entities=False, no_network=True)
Utilizar bibliotecas seguras
python
import defusedxml.ElementTree as ET
Validación sólida de esquemas
python
schema.validate(input_xml)
No concatenar cadenas XML
Enfoque más seguro:
python
el = Element("usuario") name_tag.text = user_input
Cuadro comparativo
| Tipo | Objetivo | Gravedad | Impacto |
|---|---|---|---|
| Inyección XML | Manipulación de estructuras | Medio-Alto | Bypass lógico |
| Inyección XPath | Control de consultas | Alta | Acceso no autorizado |
| XXE | Mal uso del parser | Alta | Lectura de archivos / SSRF |
| Inyección de esquemas | Bypass de validación | Medio | Riesgos de integridad |

Inyección XML en pruebas de penetración automatizadas
Las plataformas modernas de pruebas de penetración basadas en IA, como Penligent, realizan mutación de estructuras, XML fuzzing, pruebas de carga útil XPath y detección de errores de configuración del analizador sintáctico. Estas plataformas:
- Descubrir superficies de ataque basadas en XML
- Identificar los puntos de inyección
- Autoaprendizaje del comportamiento del esquema
- Generar cargas útiles adaptables
- Validar el comportamiento del analizador sintáctico con varias configuraciones
Esto amplía significativamente la cobertura de detección.
Líneas de base de seguridad y recomendaciones de correcciones automatizadas
Las plataformas automatizadas también pueden proporcionar:
- Auditorías de configuración del analizador sintáctico
- Detección de bibliotecas XML no seguras
- Verificación de los ajustes de resolución de entidades
- Aplicación de la validación XSD estricta
- Bloqueo CI/CD de operaciones XML inseguras
Esto transforma la detección en medidas correctivas.
Guión de ejemplo
Reglas Semgrep - Python XML Injection / XXE / Unsafe Parsing
Crea un archivo:
semgrep-rules/python-xml-injection.yaml
yaml
"Reglas":
REGLA 1: Uso inseguro de xml.etree - el analizador por defecto es vulnerable a XXE
- id: python-unsafe-xml-etree gravedad: ERROR mensaje: | xml.etree.ElementTree no es seguro para XML no fiable. NO deshabilita la expansión de entidades externas por defecto. Use defusedxml en su lugar. metadata: cwe: "CWE-611" owasp: "A04:2021 XML External Entities" patrones:
- pattern: | import xml.etree.ElementTree as ET languages: [python]
REGLA 2: Uso directo de xml.dom.minidom - parser XML inseguro
- id: python-unsafe-xml-minidom gravedad: Mensaje de ERROR: | xml.dom.minidom no deshabilita DTDs o expansión ENTITY. NO lo utilice para XML no fiable. metadatos: cwe: "CWE-611" pattern: | import xml.dom.minidom languages: [python]
REGLA 3: XMLParser lxml peligroso con resolve_entities=True
- id: python-lxml-resolve-entities-enabled severidad: Mensaje de ERROR: | lxml XMLParser() con resolve_entities=True habilita XXE. Establezca resolve_entities=False y load_dtd=False. metadatos: cwe: "CWE-611" pattern: | XMLParser(resolve_entities=True, ...) languages: [python]
REGLA 4: lxml con load_dtd=True - peligroso
- id: python-lxml-load-dtd severidad: WARNING mensaje: | load_dtd=True habilita el procesamiento DTD y puede permitir la expansión de entidades. Desactivar a menos que sea absolutamente necesario. metadatos: cwe: "CWE-611" pattern: | XMLParser(load_dtd=True, ...) languages: [python]
REGLA 5: Falta la configuración segura del analizador sintáctico cuando se utiliza lxml.fromstring()
- id: python-lxml-fromstring-no-safe-config severidad: Mensaje de ADVERTENCIA: | lxml.fromstring() llamado sin un XMLParser endurecido. Asegúrese de que resolve_entities=False, no_network=True. metadatos: cwe: "CWE-611" patrones:
- pattern: | from lxml import etree - pattern: | etree.fromstring($XML) languages: [python]
REGLA 6: No usar defusedxml al analizar XML externo
- id: python-defusedxml-not-used severity: INFO message: | Missing use of defusedxml, recommended for secure XML parsing in Python. metadata: cwe: "CWE-611" pattern-either:
- patrón: | ET.parse($X) - pattern: | etree.parse($X) idiomas: [python]
REGLA 7: xmltodict sin forzar parser desactivado
- id: python-xmltodict-unsafe gravedad: ADVERTENCIA mensaje: | xmltodict puede invocar un analizador XML subyacente que permite XXE. Utilice
defusedxmlpatrón: | xmltodict.parse($X) languages: [python]
REGLA 8: Uso peligroso de eval() en entradas derivadas de XML
- id: python-eval-from-xml severity: mensaje CRITICAL: | eval() en entrada derivada de XML puede llevar a RCE. Nunca evalúe valores XML analizados directamente. metadatos: cwe: "CWE-95" owasp: "A03:2021 Injection" patterns:
- patrón: | $VAL = $XML.xpath(...) - pattern: | eval($VAL) languages: [python]
REGLA 9: Pickle.loads inseguro en datos XML
- id: python-pickle-on-xml gravedad: mensaje CRITICAL: | pickle.loads() sobre entrada derivada de XML puede llevar a la ejecución de código arbitrario. Evite pickle en datos de usuario. metadatos: cwe: "CWE-502" patrones:
- patrón: | $DATA = etree.fromstring(...) - patrón: | pickle.loads($DATA) languages: [python]`
Escáner Python SAST completo
Esto complementa Semgrep mediante la exploración de los patrones de riesgo, incluyendo:
- Importaciones no seguras de analizadores XML
- ENTITY / DOCTYPE uso
evalúe,exec,pepinillo,mariscal,yaml.loadpatrones- Activadores XXE en
.xml,.xsd,.wsdlarchivos
Crear: python_sast_scanner.py
python
`#!/usr/bin/env python3″"" python_sast_scanner.py Ligero y rápido escáner SAST específico de Python especializado en:
- Inyección XML / XXE
- uso inseguro del analizador sintáctico
- Funciones peligrosas (eval, exec, pickle.loads, yaml.load) Seguro para CI; no ejecuta ningún código. Salida JSON y salida distinta de cero si se encuentra algo. """import os, re, json, sys PATTERNS = {# XML / XXE "xml_etree": r "import\s+xml\.etree\.ElementTree", "xml_minidom": r "import\s+xml\.dom\.minidom", "lxml_resolve_entities": r "resolve_entities\s*=\sTrue", "lxml_load_dtd": r "load_dtd\s=\s*True", "doctype_in_xml": r"<!DOCTYPE", "entity_in_xml": r"<!ENTITY",

Funciones peligrosas
"eval_usage": r"\\beval\\s*\\(","exec_usage": r"\\bexec\\s*\\(","pickle_loads": r"pickle\\.loads\\s*\\(","marshal_loads": r"marshal\\.loads\\s*\\(","yaml_unsafe_load": r"yaml\\.load\\s*\\(",
} IGNORED = {".git", "venv", "env", "pycache", "dist", "build", "node_modules"} def scan_file(path): findings = []try:with open(path, "r", encoding="utf-8″, errors="ignore") as f:for i, line in enumerate(f, 1):for rule, regex in PATTERNS.items():if re.search(regex, line): findings.append({"regla": regla, "línea": línea.strip(), "lineno": i, })except Exception:pass return findings def walk(root="."): results={}for dp, dirs, files in os.walk(root): dirs[:] = [d for d in dirs if d not in IGNORED]for f in files:if f.endswith((".py",".xml",".xsd",".wsdl")): full = os.path.join(dp, f) hits = scan_file(full)if hits: results[full] = hitsreturn results def main(): root = sys.argv[1] if len(sys.argv)>1 else "." results = walk(root)print(json.dumps({"results": results, "file_count": len(results)}, indent=2))if results: sys.exit(3) sys.exit(0) if name == "main": main()`
Qué cubre - Python SAST Scope
Inyección XML / XXE
✔ Parsers XML inseguros ✔ lxml con resolver_entidades=True ✔ Carga de DTD (potencialmente peligroso) ✔ Marcadores XXE en archivos XML almacenados.
Inyección de código
✔ eval() ✔ exec()
Deserialización insegura
✔ pickle.loads() ✔ marshal.loads() ✔ inseguro yaml.load()
Otros patrones inseguros
✔ ENTITY / DOCTYPE en .xml, .xsd, .wsdl ✔ xmltodict sin parser endurecido
Conclusión
La inyección XML sigue siendo una categoría de vulnerabilidad relevante y peligrosa. Su impacto va desde la elusión de la lógica de negocio a la divulgación de archivos y la denegación de servicio. Comprender los comportamientos XML, proteger los analizadores sintácticos, validar la estructura e incorporar pruebas de penetración automatizadas son pasos esenciales para garantizar la seguridad de las aplicaciones.

