When string formatting escalates to Remote Code Execution.
Template engines (like Jinja2, Twig, or EJS) are used to dynamically generate HTML. They securely inject variables into a static template. However, if a developer dynamically concatenates user input directly into the template string itself before rendering it, an attacker can inject template directives (e.g. `{{ ... }}`) that the engine will execute.
Because template engines have deep access to the runtime environment, SSTI almost always leads to complete server takeover (Remote Code Execution).
Never use `f-strings` or `.format()` to build a template string out of user input. Always pass user input into the template engine as a context variable.
# VULNERABLE: Modifying the template itself
from flask import render_template_string
@app.route("/hello")
def hello():
name = request.args.get('name')
# DANGER: We are concatenating user input directly into the template string!
template = f"<h1>Hello {name}</h1>"
return render_template_string(template)
# SECURE: Passing as a variable
@app.route("/hello")
def hello():
name = request.args.get('name')
# The template is static. The variable is passed safely via context.
template = "<h1>Hello {{ user_name }}</h1>"
return render_template_string(template, user_name=name)
A marketing tool allows users to customize their email footers. The backend uses Ruby's ERB templating. A user saves their footer as `<%= system('cat /etc/passwd') %>`. When the backend renders the email to send it, the ERB engine executes the `system()` call, extracting the password file and placing it straight into the outgoing email.
An attacker wants to test if a webpage is vulnerable to Server-Side Template Injection. They enter `{{ 7 * 7 }}` into a search box. What response would confirm the vulnerability?