Exploiting Server-Side Template Injection

Hey guys, today we’ll discuss one of the most found or the bug hunter can say the most critical bug found on any web application. As this kind of bug deals with the server-side of web applications, it can pretty much mess up the entire system. So we’ll start off with the basic methodology for exploiting server-side injection vulnerabilities. But first, we need to understand how template engines work. So before going further into exploitation, let’s have a discussion about template engines.

Contents

Introduction

image

Templates engines are widely used by web applications to present dynamic data or pages. It enables to make the use of static template files in your application. At runtime, the template engine replaces variables in a template file with actual values, and transforms the template into an HTML file sent to the client. This approach makes it easier to design an HTML page. So any kind of insecure user input present in the application can cause the attacker to input malicious string thus causing SSTI and can often lead to Remote Code Execution(RCE). So whatever the attacker enters into the template(malicious payload) is executed at the server-side and this is what it makes the bug to be critical.

image

This is how the template engine works in Django which is the web framework for Python. There are a lot of programming languages that makes the use of template engines and it just makes the life of developer a lot easier in a production environment. Here’s a few of them I know about

Python : Django,Genshi,Jinja,Jinja2
Java   : FreeMarker,EGL,Hamlets,JavaServer Pages
PHP    : Twig, smarty, VlibTemplate
Ruby   : eRuby,Haml

Impact of Server-Side Template Injection

As we have already discussed about the things that can happen and how the attacker can completely takeover the entire organization.In this section, we will go more in depth about the variety of attacks that can happen. Exploiting SSTI will not always give us RCE but it often leads to the exposure of sensitive data or even arbitrary files present on the server. After getting all the system info, the attacker can then exploit the other services in the same network by using a method known as “pivoting”. Cross-Site Scripting(XSS) is also possible in this kind of scenario and being a client-side,it can attack all the users visiting the website more often.

Let’s take an example of how this kind of vulnerabilities arise. I have taken this example from Portswigger.

Important note to keep in mind: Static templates that simply provide placeholders into which dynamic content is rendered are generally not vulnerable to server-side template injection.

$output = $twig->render("Dear {username},", array("username" => $user.username) );

This code isn’t vulnerable to SSTI as the username field is not controllable by the attacker. So even if the attacker tries to inject something malicious, it won’t work. The code is simply fetching the username from user object and displaying it on the web page. Twig is the template engine used by PHP scripting language. Now let’s see how a vulnerable code looks like:

$output = $twig->render("Dear " . $_GET['name']);

Here, the name parameter can be controlled by anyone and thus the code is vulnerable to SSTI. We can simply inject a basic payload like and the server will return “Dear 49” as the answer thus executing our payload.This can be considered as the basic example of server side template injection. This arises due to the poor implementation of template design by developers which aren’t aware of security implications. One can even chain SSTI with some other vulnerability for more impact. Vulnerability chaining is a well-established technique of hacker trade craft which occurs during their reconnaissance process. As hackers work to enumerate a target’s digital footprint they identify direct and peripheral vulnerabilities and weaknesses in hardware and software to exploit.

Methodology

One should know how to craft a payload for successful SSTI and to do that it is really important to understand the flow. There are lot of template engines present out there and the exploit won’t happen if I try to inject PHP payload into Jinja(Jinja being the template engine of Python). For the exploit to work, we need to have a deep understanding of back-end servers and also a bit of code analysis. There are various tools out there that can be used to identify the kind of services or web servers running or we can always manually check which is always a good practice for a pentester.

The first step towards exploitation is to find the entry-point of the vulnerability. The easiest method that one can do is by fuzzing the template with a bunch of special characters like '<>{}=%' and then look out the response. If any kind of error is thrown out then we can assume that the server actually executed that particular character and is vulnerable. The error can help us detect the template engine running and thus we can craft the payload with respect to that.

Most template languages allow you to freely input content either by using HTML tags directly or by using the template’s native syntax, which will be rendered to HTML on the back-end before the HTTP response is sent. Let’s take an example of Freemarker (Template engine for Java), the code render('Howdy ' + first_name) would render something like this: Howdy Akshay

We can exploit this by injecting XSS payload but what can we do more than XSS. The XSS is possible by adjusting some characters and then adding the actual payload. As Java is executing at the back-end, maybe we can try to inject system commands

<#assign ex="freemarker.template.utility.Execute"?new()> ${ ex("system commands") }

Other thing can be manually testing every possible payload and identifying the template engine working at the back-end. A common way of doing this is to inject arbitrary mathematical operations using syntax from different template engines.

Mitigating Server-Side Template Injection

One of the best ways to mitigate SSTI is to filter everything that is coming from the user side. Keep one thing in mind that never trust the user in such scenarios. Also, the other best way is to avoid any user injecting or modify any kind of template. Depending on the engine that the server is using, we can come up with regex to filter out malicious characters that can trigger system commands (Input Sanitization).

Updating the libraries and frameworks to the latest version. Another measure that we can take is to sandbox the entire environment. Making the use of docker container to setup the entire workspace. Sandboxing is basically isolating everything from the production environment. One of the example can be a strict docker environment having certain rules set for security.

References