Server-side template injection (SSTI)
Injection de modèle côté serveur (SSTI)
Description
La SSTI, ou Server-Side Template Injection (Injection de modèle côté serveur), est une vulnérabilité de sécurité qui se produit lorsqu'un attaquant peut injecter du code malveillant dans un moteur de modèles. Les moteurs de modèles sont couramment utilisés dans les applications web pour générer du contenu dynamique, et la SSTI se produit lorsque les entrées de l'utilisateur ne sont pas correctement validées ou assainies avant d'être incluses dans un modèle.
# Supposer que user_input contient des données contrôlées par l'utilisateur
user_input = params[:input]
# Utilisation non sécurisée de ERB
template = ERB.new("<%= #{user_input} %>")
result = template.result(binding)
# Afficher le résultat
puts result
// Vulnerable PHP code using Twig
$name = $_GET['name'];
echo $twig->render('greet.twig', ['name' => $name]);
# Code Python vulnérable utilisant Jinja2
from flask import Flask, render_template, request
app = Flask(__name__)
@app.route('/greet')
def greet():
# Injection de l'entrée utilisateur directement dans le modèle
username = request.args.get('username')
return render_template('greet.html', username=username)
Recommandation
- Évitez de créer des modèles à partir des entrées de l'utilisateur dans la mesure du possible.
- Envisagez d'utiliser un moteur de modèles simple et sans logique, tel que Mustache.
- Effectuez le rendu des modèles dans un environnement de bac à sable (sandbox) où les modules et fonctionnalités à risque sont désactivés.
- Assainissez les entrées de l'utilisateur avant de les passer au modèle.
Exemples
# app.rb
require 'sinatra'
require 'mustache'
class ExampleTemplate < Mustache
def initialize(name)
@name = name
end
def greeting
"Hello, #{@name}!"
end
end
get '/greet/:name' do
name = params['name']
template = ExampleTemplate.new(name)
erb template.render
end
<!-- index.php -->
<?php
require 'Mustache/Autoloader.php';
Mustache_Autoloader::register();
$template = new Mustache_Engine;
$name = $_GET['name'] ?? 'World';
$data = ['name' => $name];
echo $template->render('Hello, {{name}}!', $data);
?>
from flask import Flask, render_template
from flask import request
import pystache
app = Flask(__name__)
# Définir un modèle Mustache simple
template = """
<html>
<head>
<title>Greeting Page</title>
</head>
<body>
<h1>Hello, {{name}}!</h1>
</body>
</html>
"""
# Créer un moteur de rendu Mustache
mustache_renderer = pystache.Renderer()
@app.route('/')
def greet_user():
# Obtenir le paramètre de requête 'name' à partir de l'URL
user_name = request.args.get('name', 'Guest')
# Rendre le modèle avec le nom de l'utilisateur
rendered_template = mustache_renderer.render(template, {'name': user_name})
# Renvoyer le HTML rendu
return rendered_template
if __name__ == '__main__':
app.run(debug=True)
Liens
Normes
- CWE_TOP_25:
- CWE_94
- GDPR:
- ART_5
- ART_32
- PCI_STANDARDS:
- REQ_6_5
- REQ_11_3
- SOC2_CONTROLS:
- CC_2_1
- CC_3_4
- CC_4_1
- CC_7_1
- CC_7_2
- CC_7_4
- CC_7_5
- HIPAA_CONTROLS:
- SECURITY212
- SECURITY213
- SECURITY255