Le prénom qui s'est exécuté : injection de template côté serveur dans Flask
Le défi
Les cartes Peachtree exécutent ton prénom. Envoie du code de template, comme {{7*7}}. Fais afficher la SECRET_KEY par la carte.
Ce que tu vas apprendre
- Détecter une injection de template côté serveur avec une sonde arithmétique
- Distinguer Jinja2 des autres moteurs à partir de sa sortie
- Lire l'objet config de Flask depuis un template
- Expliquer pourquoi une SECRET_KEY divulguée permet de forger des sessions
- Rendre l'entrée utilisateur comme une donnée, jamais comme du code de template
Compétences testées
Prérequis
- Ce qu'est une query string
- À quoi sert un template web
Comment ça marche
Un moteur de template transforme un template et des variables en HTML. L'injection de template côté serveur survient quand l'entrée utilisateur devient une partie du template au lieu d'une variable : le moteur évalue alors tout ce que l'utilisateur a écrit.
Ici l'appli fait TEMPLATE.replace("NAME", name) et rend le résultat. {{7*7}} renvoie 49, donc l'entrée est du code. L'appli utilise l'environnement sandboxé de Jinja, qui refuse les attributs commençant par un underscore, donc les chaînes d'exécution de code finissent en SecurityError. Mais un sandbox limite seulement ce qu'une expression peut faire, pas ce qui a été donné au template : dans Flask, chaque template peut atteindre config, qui contient SECRET_KEY, la clé qui signe les cookies de session.
Erreurs fréquentes
- Taper des espaces. Un espace brut coupe la ligne de requête, et gunicorn répond 400 Invalid HTTP Version. Écris
{{config}}ou encode les espaces en%20. - Courir après l'exécution de code. Le sandbox bloque
__class__et compagnie : ces payloads ne produisent que la page 500 générique. Le secret est déjà dansconfig. - S'arrêter à 49. La sonde arithmétique prouve seulement la faille : le secret est dans
config. - Répondre avec l'URL de la base de données. La clé demandée est
SECRET_KEY.
Comment s'en protéger
- Ne jamais concaténer une entrée utilisateur dans une chaîne de template. Garde les templates statiques et passe les données en variables :
render_template_string(TEMPLATE, name=name). - Utilise un environnement sandboxé (
jinja2.sandbox.SandboxedEnvironment) si des utilisateurs doivent écrire des templates. - Fais une rotation de
SECRET_KEYaprès une fuite : toute session signée avec l'ancienne clé peut être forgée.