Link Search Menu Expand Document

Server-Side Template Injection in Python

Vulnerable example

The following snippet contains a Flask web application written in Python using Jinja2 templates in an unsafe way, concatenating user-supplied data with a template string.

@app.route("/page")
def page():

    name = request.values.get('name')

    output = Jinja2.from_string('Hello ' + name + '!').render()

    return output

The user-supplied name variable is concatenated to the template text, allowing an attacker to inject template code. The screenshot shows the attacker injecting 7*7 to demonstrate the result 49 is actually computed.

$ curl -g 'http://localhost:5000/page?name={{7*7}}'
Hello 49!

Depending on which template engine has been used, advanced payloads can be crafted to escape the template sandbox and execute code on the system. The following snippet runs a system command that adds malicious.sh in the temporary folder. The payload may vary depending on the installation.

$ curl -g 'http://localhost:5000/page?name={{''.__class__.mro()[1].__subclasses__()[46]("touch /tmp/malicious.sh",shell=True)}}'

Prevention

Python template engine API mechanisms automatically enforce the separation between code and data, providing the API are called correctly as shown in the following snippets.

Jinja2

import Jinja2
Jinja2.from_string("Hello {{name}}!").render(name=name)

Mako

from mako.template import Template
Template("Hello ${name}!").render(name=name)

Tornado

template.Template("Hello {{ name }}!").generate(name=name)

References

CWE - CWE-94: Improper Control of Generation of Code (‘Code Injection’) CWE - CWE-95: Improper Neutralization of Directives in Dynamically Evaluated Code (‘Eval Injection’) PortSwigger - Server Side Template Injection