flawopen.com/Vulnerabilities/Server-Side Template Injection (SSTI)
Server-Side Template Injection (SSTI) : cause et correction de l’injection de templates
Imaginez une entreprise qui imprime des lettres avec le modèle « Bonjour, {{ name }} ». La méthode sûre fournit à l’imprimante un modèle fixe et le nom du client comme donnée. La méthode risquée insère le texte du client dans les instructions du modèle avant l’impression. Si le moteur interprète ce texte comme de la syntaxe de template, il s’agit de Server-Side Template Injection. L’impact dépend du moteur, de sa configuration, des objets exposés et des privilèges du processus ; évaluer une expression ne signifie pas automatiquement exécuter des commandes système.
Concepts clés et termes du sous-système
- Moteur de templates
- Composant serveur, tel que Jinja ou Twig, qui analyse la syntaxe des templates et produit une sortie à partir d’un template et de données de contexte.
- Injection dans le code source du template
- Défaut où du texte externe est inséré dans le code source avant son analyse ; le moteur l’interprète alors comme une syntaxe plutôt que comme une donnée.
- Données de contexte
- Valeurs transmises séparément à un template fixe et fiable. Cette séparation empêche une valeur telle que
{{ 7 * 7 }}d’être analysée à nouveau comme du code source. - CWE-1336
- Neutralisation incorrecte d’éléments spéciaux utilisés par un moteur de templates. Cette catégorie décrit le traitement dangereux d’une entrée externe comme syntaxe de template.
Déroulement de l’attaque étape par étape
Une entrée contrôlée par l’attaquant atteint un point de template
Un champ, une valeur de profil stockée ou une autre chaîne influencée de l’extérieur atteint le code qui crée ou compile un template. Le défaut porte sur la construction du code source, pas sur le simple rendu d’une valeur.
L’application mélange données et instructions du template
L’application interpole la chaîne non fiable dans le code source du template (par exemple une f-string transmise à render_template_string) au lieu d’utiliser un template statique et une valeur de contexte séparée.
Le moteur analyse le code combiné
Le moteur interprète les expressions selon son langage et sa configuration. Une expression arithmétique inoffensive peut montrer qu’une évaluation a lieu ; cela ne prouve pas à lui seul un accès aux fichiers, aux secrets ou aux commandes système.
L’impact dépend du moteur et du déploiement
Les conséquences dépendent des objets et fonctions accessibles, du sandbox, des restrictions du moteur et des privilèges du processus web. Une RCE est possible dans certaines configurations, mais n’est pas automatique pour toute SSTI.
Mécanisme et cause racine
Une SSTI se produit lorsqu’une application incorpore du texte influencé de l’extérieur au programme du template avant son analyse. Avec Flask/Jinja, le modèle vulnérable construit une nouvelle chaîne source à partir des données de la requête et la transmet à render_template_string() ; l’échappement HTML protège la sortie et ne transforme pas un code source non fiable en donnée. La correction charge un template fixe et transmet la valeur séparément dans le contexte. Si les utilisateurs doivent rédiger des templates, exposez un modèle de données minimal et effectuez le rendu dans un worker isolé avec des limites de ressources. Le sandbox est une défense en profondeur, pas une raison d’exposer des secrets ou des objets puissants.
# 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)
# 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>
Séquence d’attaque et exemple conceptuel
- 1Source : Une valeur influencée de l’extérieur atteint un chemin de construction de template.
- 2Composition dangereuse : L’application insère cette valeur dans le code source au lieu de la transmettre séparément comme donnée de contexte.
- 3Interprétation : Le moteur analyse le code combiné. Dans un environnement de test autorisé, une expression arithmétique inoffensive peut confirmer l’évaluation.
- 4Impact conditionnel : La suite dépend du moteur, des objets exposés, de la configuration et des privilèges ; ne déduisez pas une RCE de la seule évaluation d’une expression.
Règles de prévention et de protection technique
- ✓Garder le code source fixe : Charger les templates fiables depuis des fichiers ou un loader contrôlé ; ne transmettre l’entrée utilisateur que comme valeur de contexte. Ne pas concaténer les données de requête dans le code source.
- ✓Distinguer SSTI et injection HTML : L’échappement HTML protège les contextes de sortie ; il ne corrige pas un flux où une entrée non fiable est analysée comme code de template.
- ✓Encadrer les templates rédigés par les utilisateurs : Si cette fonction est nécessaire, utiliser le sandbox du moteur pour cet usage, exposer un modèle minimal et rendre dans un worker isolé avec limites de ressources. Suivre les consignes de sécurité du moteur.
- ✓Limiter l’impact : Exécuter le moteur de rendu avec un compte sans privilèges et des accès minimaux aux fichiers, au réseau et aux secrets. Il s’agit de confinement, pas du correctif principal.
- ✓Ajouter des tests de régression : Passer une marque inoffensive telle que
{{ 7 * 7 }}comme donnée et vérifier qu’elle reste une donnée ; vérifier que les templates proviennent uniquement du loader fiable.