Team we45
March 14, 2018

Server Side Template Injection - A Crash course!

Have you noticed how some emails, even though looks like it's from a mass email campaign, are addressed to your name? That's a template engine at work. Some of the server-side template engines that are most frequently used are Smarty, Mako, Twig, and Jinja2. Web applications commonly use these template engines to present dynamic data on web pages and emails. Examples include wikis, blogs, content management systems, and marketing applications.

This feature allows embedding user input into the web application, and if not sanitized properly, could make it vulnerable to Server-Side Template Injection and potentially give remote code execution (RCE) capability to intruders.

In this blog, you will learn the basics of how to identify and exploit an SSTI, along with a few remediation suggestions.

Identifying SSTI Vulnerability

Identifying SSTI can sometimes be as easy as submitting invalid syntax in the user input, and using resulting error messages to detect the template engine in place. If the input concatenates with a server-side variable and renders it on the template, then its an indication that the template is vulnerable to SSTI. For example, the output of the following two inputs shows that the template on the server-side is vulnerable:

Input: custom_email={{5*5}}
Output: 25

Input: custom_email={{self}}
Output: Object of class _TwigTemplate_7ae62e582f8a35e5ea6cc639800ecf15b96c0d6f78db3538221c1145580ca4a5 could not be converted to string

Sometimes, the error responses may be suppressed, making it hard to identify which template engine is in use and whether it is vulnerable. But, the syntax used in these template languages are required not to clash with HTML characters, so most of these languages share the same basic syntax characteristics. We can exploit this by sending generic payloads with a single HTTP request, and probe multiple template engines at once.

Using a decision flow diagram approach as shown in the below image, you can identify which server-side template is in use and if it’s vulnerable. The diagram shows the different payloads for probing and only accounts for the four most used server-side template engines. If the output is the mathematical calculation of the payload, then the template is vulnerable.

SSTI Flow Chart

Image: Decision chart to identify which template engine is in use

Bonus note: You can use this chart to automate probing of template engines using ZAP or BURP.

Exploiting the SSTI with a Flask Application

There are multiple ways to exploit an SSTI vulnerability depending on the template engine in place. It can happen in a matter of seconds or few minutes. For example:

For a Smarty template engine, an input such as {php}echo ‘id’;{/php} can give you root command execution (RCE) access.

For Mako template engine, the below input can give you RCE access.

import os

Once you know which template is in use and if it’s vulnerable, it’s fairly easy to exploit it. If you are a developer or new security enthusiast, you are probably thinking “sure, it's easy for you to say!” Well, I developed a python flask application to show you how easy it is.

I created the flask application using one of the server-side template engines. (I’m intentionally not telling you which engine I used right now. You’ll have to figure it out yourself.) This application’s primary function is to search for stored users. If you want to try testing this method on the Flask application, you need to download the application here. (It includes instructions on how to download and run it for testing).

If you are done downloading the application, we are now ready to start! So, fire up the application and see what it looks like.

The first thing to do is to identify if the template engine is vulnerable or not, and which template is in use. (You already know this app is vulnerable, but forget that for learning sake). Using the decision flow chart we discussed earlier, try the different inputs and find out which template is in place.

demo flask application _ SSTI

Image: Demo Flask Application home page.

By now, you should know which template is in place. Based on the outputs, you would have identified the template as Jinja2.

Now, let's try to exploit this vulnerability. Jinja2 template is used by Python web frameworks. So, you can inject payloads written in python for exploitation. You can use ZAP or BURP for this stage. I’m using BURP here. As displayed in next image, we will be injecting the below payload under REQUEST tab.

This payload is requesting to provide the file contents of passwd from etc directory.

injecting payload using burp tool

Image: Injecting payload using Burp tool under REQUEST.

server side template injection

Image: Shows the response from the request.

If you are seeing what I am in seeing (above image) then voila!!!! We got a hit. As you can see, the payload that we injected returned with a 200 OK response. Based on our REQUEST, the response was the display of contents from passwd file in the /etc folder. It shows the details of the server-side file system. From here, you could probably find multiple ways to exploit the system using different tools. I further exploited it using a TPLmap tool.

I won't teach you how to exploit this using TPLmap (not in this blog anyway), but to give you an idea of the kind of potential there is to further exploit an SSTI, see the next image. The image shows that following our access to passwords from the previous injection, we were able to use it to gain shell access to their systems.

Gaining shell access using TPLmap tool

Image: Gaining shell access using TPLmap tool.

Remediating an SSTI

Now that you know what SSTI is, and a bit of how to detect and exploit it, you should probably know a bit about how to remediate this. If you are a developer, then this is for you. Remediations differ depending on the different template engines in place. So, the follow remediations are conceptual and can be applied to all template engines.

  1. Sanitization:
  2. Pass user inputs into templates as parameters. Sanitize the input before passing it into the templates by removing unwanted and risky characters before parsing the data. This minimizes the vulnerabilities for any malicious probing of your templates.
  3. Sandboxing:
  4. If allowing certain risky characters is a business requirement to render certain attributes of a template, assume that malicious code execution is inevitable. Then sandboxing the template environment in a docker container is probably a safer option. With this option, you can use the docker security to craft a secure environment that limits any malicious activities.