Server-Side Template Injection (aka Template Injection)


Template Injection, also known as Server-Side Template Injection (SSTI) is a vulnerability class that has established the foundations for the exploitation techniques in multiple template engines. The exploitation of this type of issue will require specific knowledge of the template library or the language being used under the hood.

First, let us start with an introduction about the vulnerability which is needed to get a good understanding of the attack patterns to recognize potential vulnerabilities.

Template Injection

A template engine enables you to use 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.

Although the templates were deployed statically, the advent of highly configurable service (SaaS) led several template libraries to be exposed directly on the internet. These seemingly very limited libraries are actually much more powerful than some developers might think.

Data Binding

In a template, the developer will define both static content and place holder for dynamic values. At runtime, the template will be processed by its engine to map dynamic values references in the template.

Template is a form of script that will do much more than just simple data binding. Because data structure can be complex (think about list and nested objects), templates provide some capabilities similar to programming. For instance, the template engine might allow to reach field from objects.

Example of Simple Template:Hello {{firstName}} {{lastName}}!

Nested properties like the below will not be evaluated directly by the language. The dynamic value user.firstName inside the place holder will be parsed by the engine. The engine will make under the hood the call to the method or field firstName. The syntax is generally simple and compact for ease of use. The syntax is often powerful enough to escape the context of simple data binding.

Example of Nested properties:Hello {{user.firstName}} {{user.lastName}}!

In order to abuse a template engine, the attacker will need to take advantage of the capabilities made available.

If the engine allows the access of fields, we might be able to access interesting internal data structure. Internal data structure could have interesting state to override. They may expose powerful types.

If the engine allows function calls, we are going to target function that read files, execute commands or access internal states of the application.


Although there are a huge number of templating languages, many of them use very similar syntax that is specifically chosen not to clash with HTML characters. As a result, it can be relatively simple to create probing payloads to test which template engine is being used.

Simply submitting invalid syntax is often enough because the resulting error message will tell you exactly what the template engine is, and sometimes even which version. For example, the invalid expression <%=foobar%> triggers the following response from the Ruby-based ERB engine:

(erb):1:in `<main>': undefined local variable or method `foobar' for main:Object (NameError)
from /usr/lib/ruby/2.5.0/erb.rb:876:in `eval'
from /usr/lib/ruby/2.5.0/erb.rb:876:in `result'
from -e:4:in `<main>'

Otherwise, you’ll need to manually test different language-specific payloads and study how they are interpreted by the template engine. Using a process of elimination based on which syntax appears to be valid or invalid, you can narrow down the options quicker than you might think. A common way of doing this is to inject arbitrary mathematical operations using syntax from different template engines. You can then observe whether they are successfully evaluated. To help with this process, you can use a decision tree similar to the following:

server-side template injection

James Kettles as come up with this decision tree which can be used to identify the template technology used. It is composed of simple evaluation. Those expression will not work with every technology. Because these are very basic expression, they are less likely to become obsolete when a new version of a library is released. Method names allowed and advanced syntax's are likely to evolve over time.

You should be aware that the same payload can sometimes return a successful response in more than one template language. For example, the payload {{7*'7'}} returns 49 in Twig and 7777777 in Jinja2. Therefore, it is important not to jump to conclusions based on a single successful response.

What is server-side template injection?

Server-side template injection is when an attacker is able to use native template syntax to inject a malicious payload into a template, which is then executed server-side.

Template engines are designed to generate web pages by combining fixed templates with volatile data. Server-side template injection attacks can occur when user input is concatenated directly into a template, rather than passed in as data. This allows attackers to inject arbitrary template directives in order to manipulate the template engine, often enabling them to take complete control of the server. As the name suggests, server-side template injection payloads are delivered and evaluated server-side, potentially making them much more dangerous than a typical client-side template injection.