Web ApplicationJanuary 1, 2023A guide to Server-Side Template Injection (SSTI)

Server-Side Template Injection (SSTI) occurs when an attacker injects a malicious payload into a template using native template syntax and causes it to execute on the server.

Template engines generate web pages by combining static templates with transient data. Server-side template injection attacks can occur when user input is directly combined into a template rather than being provided as data. As a result, attackers can control the template engine by injecting arbitrary template directives. Since they are supplied and assessed on the server, server-side template injection payloads may be significantly more harmful than ordinary client-side template injections.

Let’s look at the following list of some of the most well-known template engines:

  • PHP: Smarty, Twigs
  • Java: Velocity, Freemaker
  • Python: Jinja, Mako, Tornado
  • JavaScript: – Jade, Rage
  • Ruby: Liquid

A malicious server-side template injection payload can be executed on the server and lead to remote code execution when input validation is not correctly handled on the server side.

What is the Impact of Server-Side Template Injection?

Depending on the concerned template engine and the precise manner in which the application uses it, server-side template injection vulnerabilities might leave websites open to a number of attacks. These flaws don’t actually represent a security concern except in extremely unusual situations. However, server-side template injection can frequently have disastrous effects.

At the extreme end of the spectrum, an attacker may succeed in executing remote code, seizing total control of the back-end server, and utilizing it to launch other attacks on the internal architecture.

An attacker can frequently utilize server-side template injection as the foundation for a variety of different attacks, potentially acquiring read access to sensitive data and arbitrary files on the server, even when full remote code execution is not possible.

  • ${“aaaa”} – “aaaa” 
  • ${99999+1} – 100000. 
  • #{7*7} – 49 
  • ${{7*7}} – 49 
  • ${{request}}, ${{session}}, {{faceContext}} 

Finding a weakness is the initial step in its exploitation, as it is with any vulnerability. The initial strategy that might be the simplest is to try fuzzifying the template by inserting a string of special characters that are frequently found in template expressions, like the polyglot ${{<%[%'”}}%\. You should check for variations between the response with ordinary data on the parameter and the supplied payload to determine whether the server is vulnerable. It will be simple to determine the server’s vulnerability and even the engine that is operating if an error is thrown.

But you could also find a vulnerable server if you were expecting it to reflect the given payload and it is not being reflected, or if there are some missing characters in the response.

Detect-Code Context 

  • In some instances, user input is contained within a template expression: engine.render. (“Hello, {{“+greeting+”}}”, data)
  • A URL similar to this one might be used to access that page: http://vulnerable-website.com/?greeting=data.username
  • The username will not be returned if the greeting parameter is changed to a different value, but if you access something like http://vulnerable-website.com/?greeting=data.usernamehello then the username will be returned. It will be simpler to identify the server’s vulnerability if an error is thrown during these tests.


Identifying the template engine in use comes after spotting template injection. This process can occasionally be as simple as submitting incorrect syntax because template engines may recognize themselves in the error reports. This method is not suitable for automation and fails when error messages are suppressed. Instead, we’ve used a decision tree with language-specific payloads to automate this in Burp Suite. The words “success” and “failure” are denoted by green and red arrows, respectively. A same payload may occasionally yield several different success replies; for instance, the probe {{7*’7′}} might return 49 in Twig, 7777777 in Jinja2, and neither if no template language was in use.

SSTI Payload Tree 

For exploitation, we are going to use Try hack me box https://tryhackme.com/room/learnssti 

  • Let’s change the string test to “user” and see whether the user gets reflected or not.

  • We can see that it is reflecting the content that we are putting in the URL. Now let’s try to detect if it is vulnerable to SSTI. For that, we need to use some characters that are often used in template engines ${{<%[%'”}}%
  • Let us try and manually add these characters.

  • This produces an Internal Server Error, which means that our code is not getting executed

  • After getting an internal server error, we can confirm that this is due to a “${{” and the backend server is facing the error.
  • Now let’s try some queries, like multiplication. Eg ${{7*7}}

  • After trying ${{7*7}} we are able to get a calculated query from the server.
  • Now let’s identify the server by using the SSTI payload tree.

  • As seen in the image above we can identify that the web server is Jinja2. By using the  payload {{ ”.__class__.__mro__[1].__subclasses__()[401](“whoami”, shell=True, stdout=-1).communicate() }},  we can gather information of the server (here, let’s get the information of the host name.)

  • Here, we can see that we have gathered the host name of the user Jake through SSTI.

How to Prevent SSTI Flaws

The best method to protect websites from SSTI vulnerabilities is to never allow users to change or create templates. However, if a business emergency arises, the following options are available:


Potentially dangerous elements must be located and eliminated before they are utilized in the template. It’s crucial to efficiently analyze user data flows as a result. There are a variety of ways to do this (use of regex, white lists of authorized expressions, etc.).


  • The objective is to create a secure environment in which risky modules and functions are disabled. The interpretation of user-supplied data cannot grant access to other features or data.
  • Unfortunately, sandbox environments are difficult to set up and can be bypassed by misconfiguration or oversight.

Logic-free Template

  • There are logic-free engine templates that try to keep visual rendering and code interpretation apart. Mustache web template is one of the most popular web template systems.
  • It lacks explicit control flow statements; instead, all control is data-driven, so Mustache templates cannot include application logic.
  • As a result, RCE attacks are no longer feasible, dramatically lowering the risk of attacks.

TL;DR: Walkthrough

By partnering with Redfox Security, you’ll get the best security and technical skills required to execute an effective and thorough penetration test. Our offensive security experts have years of experience assisting organizations in protecting their digital assets through penetration testing services. To schedule a call with one of our technical specialists, call 1-800-917-0850 now.

Redfox Security is a diverse network of expert security consultants with a global mindset and a collaborative culture. With a combination of data-driven, research-based, and manual testing methodologies, we proudly deliver robust security solutions.

“Join us on our journey of growth and development by signing up for our comprehensive courses, if you want to excel in the field of cybersecurity.”

Redfox Security Team

by Redfox Security Team

Redfox Security is a fast-growing cyber security consulting firm, spread across 4 countries. With over 10 years of global security consulting experience, we help businesses strengthen their security posture. Our mission is to help businesses grow securely with our top-line cyber security consulting services – and that’s exactly what we do.