Server-side template injection (SSTI)
Server-side template injection (SSTI)
Description
SSTI, or Server-Side Template Injection, is a security vulnerability that occurs when an attacker can inject malicious code into a template engine. Template engines are commonly used in web applications to generate dynamic content, and SSTI occurs when user input is not properly validated or sanitized before being included in a template.
# Assume user_input contains user-controlled data
user_input = params[:input]
# Unsafe usage of ERB
template = ERB.new("<%= #{user_input} %>")
result = template.result(binding)
# Output the result
puts result
// Vulnerable PHP code using Twig
$name = $_GET['name'];
echo $twig->render('greet.twig', ['name' => $name]);
# Vulnerable Python code using Jinja2
from flask import Flask, render_template, request
app = Flask(__name__)
@app.route('/greet')
def greet():
# Injecting user input directly into the template
username = request.args.get('username')
return render_template('greet.html', username=username)
Recommendation
- Avoid creating templates from user input whenever possible
- Consider using a simple logic-less template engine such as Mustache
- Render templates in a sandbox environment where risky modules and features are disabled.
- Sanitize user input before passing it into the template
Examples
# 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__)
# Define a simple Mustache template
template = """
<html>
<head>
<title>Greeting Page</title>
</head>
<body>
<h1>Hello, {{name}}!</h1>
</body>
</html>
"""
# Create a Mustache renderer
mustache_renderer = pystache.Renderer()
@app.route('/')
def greet_user():
# Get the 'name' query parameter from the URL
user_name = request.args.get('name', 'Guest')
# Render the template with the user's name
rendered_template = mustache_renderer.render(template, {'name': user_name})
# Return the rendered HTML
return rendered_template
if __name__ == '__main__':
app.run(debug=True)
Links
Standards
- 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