User-provided data, such as URL parameters, POST data payloads, or cookies, should always be considered untrusted and tainted. Constructing HTML
content directly from tainted data enables attacker(s) to inject special crafted values to abuse template engine’s rendering process. Successful
server side template injection (SSTI) attack can lead to arbitrary file read or operating system commands execution.
Template engine are used by web server to render rich HTML content, generally web pages or emails. Template injection usually happens when the
template content has been dynamically generated from unvalidated user inputs.
This problem can be avoided by:
- Using static template that are read from files rather than building templates dynamically
- Using template variables to inject dynamic values at render time
- Using template engine advanced control structure (like blocks or include) to dynamically build complex templates
Noncompliant Code Example
from flask import request, render_template_string
# /hello?username={{config}} will display the entire flask configuration and potential secrets
@app.route('/hello')
def hello():
username = request.args.get('username')
template = f"<p>Hello {username}</p>" # User input is used directly in the string to be rendered
return render_template_string(template) # Noncompliant
Compliant Solution
from flask import request, render_template_string
@app.route('/hello')
def hello():
username = request.args.get('username')
template = "<p>Hello {{ name }}</p>"
return render_template_string(template, name=username) # Compliant
See