12-02-2019 / From 0 to pentesting hero

SSTI - Server-Side Template Injections

In this episode of "from 0 to pentesting hero" we'll talk about template engines. This time we'll use Python as an example and Flask1 framework, in which we will use Jinja22.

Long ago, pieces of code responsible for application logic and content displayed to the user were stored in one file.

As you can guess, such mix was not only difficult to control, but also caused a lot of bugs in applications.

Because of that, template engines were created. Thanks to them, the logic of the page is stored in one file and everything that is to be displayed in the second.

Initially, these engines were simple and in most cases worked like good old "find and replace" feature known from word processors.

With time, however, their capabilities have increased drastically. It can be observed on the example of Jinja2 documentation, which is a popular engine used in applications created in Python.

Currently, it can be said that these engines are programming languages themselves. And usually you can perform a lot of potentially dangerous activities such as reading any file or executing any code.

So what will happen when a programmer forgets how powerful tool he has and uses it in a wrong way?

We'll take a look at the example application in Flask.

name = request.values.get('name')
return Jinja2.from_string('Hi ' + name).render()

Here, we take the parameter name from the user and then display it using the function from_string.

So where is the vulnerability today?

When we take a closer look at the documentation of the function from_string, we can notice that its source parameter is the content of the template, that is then parsed and returned as a Template object.

How from_string function works

So if it is a template content - this string can contain any function that this template engine supports.

And because this string is controlled by the user - using the name parameter - the user can execute any code that the template engine allows.

In a standard situation, we would not know that this application uses Jinja2.

First, it would be necessary to identify the engine we are dealing with.

We can use a simple infographics published by the creators of the Burp 3, which in a few steps lets us check what kind of tool we target.

Detect template engine
https://portswigger.net/blog/server-side-template-injection

We already know what engine this is and we will use the correct payload:

{{7*'7'}}

The result of the multiplication was returned. So we are sure that our command worked.

SSTI example

So what can we do now?

Of course, we could review the documentation in search of interesting functionalities.

However, it is worth checking if someone has done it before us.

On Github, we can find a list of sample queries.

SSTI payload for Jinja2

I will try to read the secret file here. So I have to change the path to the file.

{{ ''.__class__.__mro__[2].__subclasses__()[40]('/etc/passwd').read() }}

You can also use tools that will test which engine4 we have for us.

After using it, we see that it correctly recognized engine, the system and also displayed what you can do with it.

tplmap

So how to protect yourself from this vulnerability?

Use the engines as intended. Therefore, remember that the user should never provide template content.

He can only specify the content of parameter that will be displayed by this template.