SSTI Vulnerability — Server-Side Template Injection Execution AND Exploration

Willian Seiffert
stolabs
Published in
4 min readSep 27, 2022

As the name implies, it’s a vulnerability that occurs on the server side, giving the idea that the attacker will induce the server to perform some action that theoretically shouldn’t. Templates are basically dynamic parts of the content that have the ability to evaluate arbitrary code. If there’s a web page where the content is pretty much the same, but only some parts of it change, there’s a good chance that page is using templates.

THE IMPACT

Most of the time the impact is critical, and it’s likely to achieve RCE and take full control of the server, although the way in which you achieve that can vary from how the application is implementing it to which model of template is being used. It is important to note that the vulnerability can exist anywhere, not just on the server side, but wherever there is a template available.

It’s hard to find an SSTI that doesn’t have a big impact, even if initially doesn’t seem like it, the chance of escalating to another vulnerability or gaining access to sensitive data and access files that the shouldn’t be allowed is possible.

THE IDENTIFICATION

The first battle is to detect the template engine, a simple example would be looking for inputs, URLs that allow us to send data and looking for an “exception” when sending special characters like ${{<%[%’”}}%\, often used for perform actions in templates, which may indicate a possible SSTI.

It can also be identified manually or with brute-force, using payload lists related to the various templates that exist today.

THE EXECUTION

I created a server with an application in flask and jinja2 vulnerable to SSTI for a simple demonstration:

Viewing the exception after sending the payload with special characters:

After detecting that the template being used is jinja2, it would be interesting to access its documentation and understand how to use it to later start a more solid attack.

THE EXPLORATION

If the documentation is not enough, an alternative is to explore the environment and discover the objects that you can access.

These objects that are present in templates engines, can show a path depending on how much they are exposed. With some objects, we can view environment variables, read files, execute commands and take advantage of that.

In jinja2 for example, you can use this payload to execute OS commands:

{{self._TemplateReference__context.cycler.__init__.__globals__.os.popen(‘id’).read()}}

Using the same payload, but now to list directories and files:

{{self._TemplateReference__context.cycler.__init__.__globals__.os.popen(‘ls -la’).read()}}

Being able to scale to a RCE:

And getting it:

In Ruby, to list directories and files, you can use:

<%= Dir.entries(‘/’) %>

In Java to list environment variables you can use:

${T(java.lang.System).getenv()}

As we can see, there are several templates and each one has a different way of communicating because they were developed in different ways and languages, which can be difficult. To help with researches, we can find several wordlists on the web with different payloads for different types of templates.

THE PREVENTION

One of the ways to prevent Server Side Template Injection is to not allow any user to submit new templates or modify them, as in this example, concatenating the user input with the template string, on line 11.

Returning the result of the calculation, without considering the input as a string:

We can fix this by passing the variable to the template context, as in line 11.

Returning the input as a string:

Sometimes it’s almost inevitable to block all arbitrary code executions, having to deploy your template in a locked container.

THE CONCLUSION

In general, the server-side template injection vulnerability is not complex, making it easy to exploit once detected, but it usually goes unnoticed if you don’t try to find it directly. It can also be confused with a Cross-Site Scripting (XSS) vulnerability, due to the possibility of executing code where it shouldn’t, but unlike XSS, SSTI directly attacks internal servers, being most of the time, more critical.

That’s it for now, thank you! =)

References:
>CURL: https://curl.se/docs/manpage.html

>PortSwigger Research: https://portswigger.net/research/server-side-template-injection

>tplmap: https://github.com/epinna/tplmap

>PayloadsAllTheThings(SSTI): https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection

>Payloadbox(SSTI): https://github.com/payloadbox/ssti-payloads

--

--