FlawOpen

flawopen.com/SSTI/Jinja2

¿Es seguro render_template_string() de Jinja2?

CWE-1336: Inyección de plantillas del lado del servidorPágina de referencia
Respuesta breve

Usa render_template_string() solo si el código de la aplicación controla la cadena de la plantilla. Si se inserta entrada no confiable en esa cadena antes de que Jinja la analice, se produce SSTI. En el entorno Jinja predeterminado y sin sandbox de Flask, el impacto puede incluir ejecución de código según los objetos accesibles, la configuración y la aplicación concreta; no ocurre automáticamente en todos los despliegues.

VULNERABLE
# All four are the same bug
render_template_string(f"Hi {name}")
render_template_string("Hi " + name)
render_template_string("Hi %s" % name)
render_template_string("Hi {}".format(name))

# A very common real-world shape:
@app.errorhandler(404)
def not_found(e):
    return render_template_string(
        f"<h1>No such page: "
        f"{request.path}</h1>"
    ), 404
# The URL path is attacker-controlled.
CORREGIDO
# Template is a literal; the user value
# arrives as a named context variable
render_template_string(
    "Hi {{ name }}", name=name
)

# Better still, a real template file
render_template("greeting.html",
                name=name)

# For the 404 case, no template
# evaluation is needed at all:
return render_template("404.html",
                       path=request.path), 404

Qué implica que el atacante controle la plantilla

Flask ofrece por defecto a las plantillas variables globales de la aplicación como config, request y session. Si el atacante controla el código fuente de la plantilla, Jinja evalúa sus expresiones con los objetos disponibles en ese entorno. El impacto depende de los objetos y capacidades que exponga la aplicación. Una expresión aritmética inocua puede confirmar que hubo evaluación, pero no demuestra por sí sola la ejecución de código ni qué datos son accesibles.

Una plantilla puede exponer valores sensibles si la aplicación los incluyó en el contexto. Por ejemplo, config de Flask puede contener SECRET_KEY o ajustes de base de datos, aunque cada despliegue es distinto. No incluyas secretos en datos visibles para las plantillas y no confundas el escape de salida con una barrera contra la evaluación.

CVE-2024-56201 es un caso distinto

Esta vulnerabilidad del compilador de Jinja es independiente y no hace falta para que exista una SSTI común: CVE-2024-56201 afecta a Jinja 3.0.0–3.1.4 cuando el atacante puede controlar tanto el contenido como el nombre de una plantilla. En esa condición era posible ejecutar código Python arbitrario incluso con el sandbox. Jinja 3.1.5 corrigió el problema. Consulta el aviso y actualiza si tu aplicación acepta plantillas o nombres proporcionados por atacantes.

Dónde suele aparecer

Este patrón puede aparecer en páginas de error que reflejan la ruta solicitada, funciones administrativas de plantillas de correo, personalización por cliente y endpoints de vista previa o depuración que no deberían estar expuestos.

Preguntas frecuentes

¿El autoescape protege contra esto?

No. El autoescape escapa los valores renderizados para reducir el riesgo de XSS en la salida. No evita que una cadena del usuario se compile como código de plantilla. Son controles para etapas distintas.

¿Y si necesito aceptar plantillas de usuarios, por ejemplo para personalizar correos?

Jinja ofrece SandboxedEnvironment para plantillas de usuario, pero su documentación advierte que no constituye una seguridad perfecta. Pasa únicamente los datos necesarios, evita objetos con efectos secundarios y limita CPU, memoria y procesos fuera del motor. El sandbox no hace seguro interpolar entrada no confiable antes de analizar la plantilla.

¿Cómo localizo el problema en un código existente?

Busca render_template_string y comprueba que el primer argumento sea una cadena fija controlada por la aplicación. Pasa los valores del usuario como variables de contexto con nombre o usa un archivo de plantilla. Revisa también las API que compilan plantillas dinámicamente y permiten controlar sus nombres.

Referencias

Véase también SSTI: causa, impacto y corrección de template injection ¿Qué es la inyección de plantillas del lado del servidor? SSTI en FreeMarker y Velocity: seguridad de plantillas