FlawOpen

flawopen.com/SSTI/Jinja2

O render_template_string() do Jinja2 é seguro?

CWE-1336: Injeção de template no lado do servidorPágina de referência
Resposta curta

Use render_template_string() somente quando o código da aplicação controlar a string do template. Se dados não confiáveis forem inseridos nessa string antes de o Jinja analisá-la, ocorre SSTI. No ambiente Jinja padrão e sem sandbox do Flask, o impacto pode incluir execução de código, conforme os objetos acessíveis, a configuração e a aplicação; isso não acontece automaticamente em toda implantação.

VULNERÁVEL
# 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.
CORRIGIDO
# 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

O que muda quando o template é controlado por um invasor

Por padrão, o Flask disponibiliza aos templates globais da aplicação como config, request e session. Se o invasor controla o código-fonte do template, o Jinja avalia as expressões usando os objetos disponíveis nesse ambiente. O impacto depende dos objetos e recursos expostos pela aplicação. Uma expressão aritmética inofensiva pode confirmar que houve avaliação, mas não prova, por si só, execução de código nem quais dados estão acessíveis.

Um template pode expor valores sensíveis se a aplicação os colocou no contexto. Por exemplo, config do Flask pode conter SECRET_KEY ou configurações de banco de dados, mas cada implantação é diferente. Não coloque segredos em dados visíveis aos templates e não trate escape de saída como proteção contra avaliação do template.

A CVE-2024-56201 é um caso distinto

Esta é uma vulnerabilidade separada do compilador do Jinja, não um requisito para SSTI comum: CVE-2024-56201 afeta Jinja 3.0.0 a 3.1.4 quando o invasor consegue controlar tanto o conteúdo quanto o nome do template. Nessa condição, era possível executar código Python arbitrário mesmo com o sandbox. O Jinja 3.1.5 corrigiu o problema. Consulte o aviso e atualize se sua aplicação aceita templates ou nomes de arquivo fornecidos por invasores.

Onde isso costuma aparecer

Esse padrão pode surgir em páginas de erro que repetem o caminho solicitado, recursos administrativos de templates de e-mail, personalização por cliente e endpoints de pré-visualização ou depuração que não deveriam estar publicados.

Perguntas frequentes

O autoescape protege contra isso?

Não. O autoescape codifica valores renderizados para reduzir XSS na saída. Ele não impede que uma string fornecida pelo usuário seja compilada como código de template. São controles aplicados em etapas diferentes.

E se eu precisar aceitar templates de usuários, como para personalizar e-mails?

O Jinja oferece SandboxedEnvironment para templates criados por usuários, mas a documentação alerta que ele não é uma segurança perfeita. Passe apenas os dados necessários, evite objetos com efeitos colaterais e limite CPU, memória e processos fora do mecanismo de templates. O sandbox não torna seguro interpolar dados não confiáveis antes da análise do template.

Como encontro esse problema no código existente?

Procure render_template_string e confirme que o primeiro argumento é uma string fixa controlada pela aplicação. Passe valores do usuário como variáveis nomeadas de contexto ou use um arquivo de template. Revise também APIs que compilam templates dinamicamente e permitem controlar seus nomes.

Referências

Veja também SSTI: causa, impacto e correção de template injection O que é injeção de template no servidor? FreeMarker e Velocity SSTI: segurança de templates