FlawOpen

flawopen.com/Vulnerabilities/Server-Side Template Injection (SSTI)

Server-Side Template Injection (SSTI): causa e correção

Impact depends on reachable template behavior CWE-1336 Template Engine Security
💡 Explicação simples — dados ou instruções da impressora

Imagine uma empresa que imprime cartas usando o modelo “Olá, {{ name }}”. O processo seguro fornece ao impressor um modelo fixo e o nome do cliente como dado. O processo inseguro insere o texto do cliente nas instruções do modelo antes de imprimi-lo. Se o mecanismo interpretar esse texto como sintaxe de template, ocorre Server-Side Template Injection. O impacto depende do mecanismo, da configuração, dos objetos disponíveis e das permissões do processo; avaliar uma expressão não significa executar comandos do sistema.

Alvo: composição do código-fonte de templates e renderização no servidor em mecanismos como Jinja, Twig, FreeMarker e ERB.
Limite vulnerável: entrada não confiável é compilada ou analisada como código-fonte de template, em vez de ser passada como valor a um template confiável.
Impacto: avaliação de expressões; consequências adicionais dependem dos recursos do mecanismo, objetos expostos, sandbox e privilégios do processo.
Correção: mantenha o código-fonte confiável e estático; passe entrada não confiável somente como dado de contexto. Isole templates escritos por usuários se esse recurso for necessário.

Conceitos principais e termos do subsistema

Mecanismo de template
Componente de servidor, como Jinja ou Twig, que analisa a sintaxe de templates e gera saída usando um template e dados de contexto.
Injeção no código-fonte do template
Falha em que texto externo é incluído no código-fonte antes da análise, fazendo o mecanismo interpretar o texto como sintaxe em vez de dados.
Dados de contexto
Valores passados separadamente a um template fixo e confiável. A separação correta impede que um valor como {{ 7 * 7 }} seja analisado novamente como código-fonte.
CWE-1336
Neutralização incorreta de elementos especiais usados em um mecanismo de template. Descreve o processamento inseguro de entrada externa como sintaxe de template.

Fluxo de ataque passo a passo

Step 1

Entrada controlada pelo atacante chega ao template

Um campo, valor de perfil armazenado ou outra string influenciada externamente chega ao código que cria ou compila um template. O defeito está na composição do código-fonte, não na simples renderização de um valor.

Step 2

A aplicação mistura dados e instruções do template

A aplicação interpola a string não confiável no código-fonte do template (por exemplo, uma f-string enviada a render_template_string) em vez de usar template estático e valor de contexto separado.

Step 3

O mecanismo analisa o código combinado

O mecanismo interpreta expressões conforme sua linguagem e configuração. Uma expressão aritmética inofensiva pode demonstrar a avaliação; isso, por si só, não comprova acesso a arquivos, segredos ou comandos do sistema.

Step 4

O impacto depende dos recursos e da implantação

O impacto adicional depende dos objetos e funções acessíveis, sandbox, restrições do mecanismo e privilégios do processo web. RCE é possível em algumas configurações, mas não é consequência automática de todo SSTI.

Mecanismo e causa raiz

SSTI ocorre quando a aplicação permite que texto influenciado externamente passe a fazer parte do programa do template antes da análise. No Flask/Jinja, o padrão vulnerável monta uma nova string-fonte com dados da requisição e a envia a render_template_string(); escape de HTML protege a saída e não transforma código-fonte não confiável em dado. A correção usa um template fixo e passa o valor separadamente como contexto. Se usuários precisarem criar templates, exponha um modelo mínimo de dados e renderize em um worker isolado com limites de recursos; sandbox é defesa em profundidade, não motivo para expor segredos ou objetos poderosos.

flask_app.py (Padrão vulnerável)Vulnerável
# VULNERABLE: request data becomes template source before parsing.
from flask import Flask, request, render_template_string
app = Flask(__name__)

@app.route("/greet")
def greet():
    name = request.args.get("name", "Guest")
    # A value such as {{ 7 * 7 }} is interpreted by the template engine.
    source = f"<h1>Welcome, {name}!</h1>"
    return render_template_string(source)
flask_app.py (Protegido)Protegido
# HARDENED: fixed template source; request data stays a context value.
from flask import Flask, request, render_template
app = Flask(__name__)

@app.route("/greet")
def greet():
    name = request.args.get("name", "Guest")
    return render_template("greet.html", name=name)

# templates/greet.html is trusted, static source:
# <h1>Welcome, {{ name }}!</h1>

Sequência do ataque e exemplo conceitual

Regras de prevenção e proteção de engenharia

Fontes primárias e tópicos de segurança relacionados:Diretório completo de segurança →
CWE-1336: injeção em mecanismo de template → OWASP WSTG: Server-Side Template Injection → Jinja: sandbox e considerações de segurança → Jinja API: templates e loaders → Flask: renderização de templates →