RSTR-SSTI-001 — Python render_template_string / Template(req.x)

Summary

User input becomes the template source itself, not the data rendered by a static template. Jinja2 and the Python string.Template family give the template author the power to execute Python expressions; if the attacker writes the template, the attacker runs Python on the server.

SSTI commonly escalates to remote code execution via the classic payload:

{{ ''.__class__.__mro__[1].__subclasses__() }}

…which walks Python's class hierarchy to find subclasses like subprocess.Popen and execute shell commands.

Severity

High.

Languages

Python.

What rastray flags

  • Template(request.x) (constructor takes user input)
  • jinja2.Template(request.x)
  • render_template_string(request.x) (Flask convenience)
  • env.from_string(request.x) (Jinja2 Environment)

How to fix it

Load templates from disk and pass user input as data:

# SAFE — the template is a static file, user input is a variable
return render_template('home.html', name=request.args.get('name'))
{# templates/home.html #}
<h1>Hello, {{ name }}</h1>   {# auto-escaped #}

render_template (no _string) is the safe sibling. The template author and the request submitter must be different people.

References