Server Side Template Injection

What are Server Side Templates..?

In simple words, Templating is a programmatic approach to simplify processing of data from one format into another. You define a template once, then you may repeatedly pass data into the template and get a result. A typical result is a text string in the form of Html (a web page), xml (for an RSS feed), or even JSON (for Javascript processing on the client).

It means that the server prepares the entire html page and sends back to browser as a document. The browser just renders the page. While in client side templating server sends JSON and client-side technology renders the DOM with JSON data.

Eg: Twig, Jade, Velocity and FreeMaker etc.

Where the problem occurs..?

We all know sometimes developers laziness or internal functionality of template engines will prompt attacker to do some malicious activities.

The possibility given by server side templates while unsafely embedding user input is Cross Site Scripting(XSS) and Remote Code Execution(RCE).

Proof Of Concept:

For demo purpose we have a sample Jinja2 template. The following code embedding the user input in a unsafe manner.

from flask import Flask, request
from jinja2 import Environment

app = Flask(__name__)
Jinja2 = Environment()

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

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

    return output

if __name__ == "__main__":
    app.run(host='0.0.0.0', port=8080)

The vulnerability is introduced here by concatenating the user-provided `name` variable to the template string. Instead, the variable should be passed to the template context.

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

Now my test app is running on port 8080. In order to detect the vulnerability existence we need to try below payloads.

{{ “ajin” }} -> ajin
{{ 2*2 }} -> 4

We have confirmed that the code is vulnerable to Server Side Template Injection (SSTI). Lets take a look at XSS vulnerability.

we can use the __mro__ attribute to access the object’s inherited classes.

As clearly shown above that our injected tuple returned back from server. In order to get root object classes we can use __subclass__ attribute to dump all classes and with index of 2 to select the class type object.

Hola 🙂 we can initiate the file system access via <type ‘file’> class. To use specified class we need to mention the index of that class. Our payload will be {{ ”.__class__.__mro__[2].__subclasses__()[40](‘/etc/passwd’).read() }} where [40] is the index of file class.

Another example we have here with Twig Template Engine.

Mitigations:

  • Sandboxing with Lua environment where potentially dangerous modules and functions have been outright removed.
  • In case of ruby its good to impliment the monkey patching.

References:

  • Nice paper by James in BlackHat Conference.
  • Automated tool to detect the SSTI Vulnerability.
  • Tornado Template Injection.

Leave A Comment

Your email address will not be published. Required fields are marked *