(SSTI) Server-side Template Injection: Explanation, Discovery, Exploitation, and Prevention
Server-side template injection (SSTI) is a vulnerability that can allow attackers to execute arbitrary code on the server.
Medusa
6 mins
Server-side template injection (SSTI) is a vulnerability that can allow attackers to execute arbitrary code on the server.
In 2017, an Australian software company called PageUp suffered a data breach that exposed the personal information of millions of job seekers. The company offered cloud-based recruitment services to major corporations and government agencies around the world.
PageUp’s HR software used a web application framework that contained a SSTI vulnerability. Cyber criminals exploited this to gain access to the underlying database.
It's important to be aware of SSTI vulnerabilities to prevent attackers from executing arbitrary code on your servers.
What are Server-Side Templates/SST?
Templates are files that define how a web application will display its content to users. They contain placeholders that are filled in with data from the application which are usually written in languages like HTML and can include variables and control structures like loops and conditionals.
Here is an example of a simple HTML template:
This template defines a basic HTML page with a title and a heading, as well as a list of items that are generated dynamically using a for loop. Placeholders in the template are indicated by double curly braces ({{% %}}
) and can contain variables, like title
and heading
, or expressions, like the loop over items
.
Templates are a fundamental part of many web frameworks and can be used to render HTML pages, email messages, and other types of content.
Some common programming languages used for server-side templates(SST) include:
PHP: PHP is a server-side scripting language that is often used to create dynamic web pages. It includes a template engine called Smarty that allows developers to separate the presentation layer from the business logic layer.
Python: Python is a general-purpose programming language that can be used for web development, among other things. The Django web framework includes a templating engine that allows developers to create reusable HTML templates.
Ruby: Ruby is a dynamic, object-oriented programming language that is often used for web development. The Ruby on Rails web framework includes a templating engine called ERB (Embedded Ruby) that allows developers to embed Ruby code in HTML templates.
JavaScript: JavaScript is a client-side scripting language that can also be used to create server-side templates. The Node.js runtime environment includes a templating engine called EJS (Embedded JavaScript) that allows developers to embed JavaScript code in HTML templates.
If you would like to watch a practical video, check out the video on YouTube.
Why are Server-Side Templates(SST) important?
Server-side templates are important because they allow web applications to separate the presentation layer from the business logic layer. By using templates, developers can create reusable components that can be used across multiple pages and views. This makes it easier to maintain and update the application over time. Additionally, templates can help prevent common security issues like cross-site scripting (XSS) by automatically escaping user input.
How do SSTI Vulnerability arise?
Server-side template injection (SSTI) occurs when an attacker is able to inject code into a server-side template, which is then executed by the server. This can occur when an application uses user input to construct a template without properly validating or sanitizing the input.
For example, consider an application that uses a templating engine to render user profiles. The templating engine uses a template file that contains placeholders for the user's name and profile picture. The application prompts the user to enter their name, which is then inserted into the template using string concatenation. However, if the user enters a name that contains template code, such as {{ 2+2 }}
, the code will be executed by the server and the result will be included in the rendered page.
SSTI can be used by attackers to execute arbitrary code on the server, including commands that allow them to run commands on the system or access sensitive data. It is a serious vulnerability that can be difficult to detect and prevent, especially in complex web applications.
Here is an example of vulnerable code that uses the Flask web framework and the Jinja2 templating engine:
This code defines a vulnerable Flask application with a single endpoint that accepts a name
parameter. This code is vulnerable to Server-Side Template Injection (SSTI) because user input was directly concatenated to the template. There is never a good reason to concatenate user input to a template. Instead, the user input should become a variable that is passed to the template, like this:
An attacker can inject malicious code into the name
parameter, which will then be executed by the server when the template is rendered. This can allow the attacker to execute arbitrary code on the server or access sensitive information.
For example, an attacker could send a request to the application with the following URL: The server would then render the following template:
Payload: {{7*7}}
SSTI Payloads
{{ 7*'7' }}
: This payload will cause the server to execute the expression7*'7'
, which will result in the string'7777777'
.{{ config.items() }}
: This payload will return a dictionary of configuration items for the server, including sensitive information like database credentials.{{ ''.__class__.__mro__[2].__subclasses__()[40]('/etc/passwd').read() }}
: This payload will execute theread
method of thefile
class on the/etc/passwd
file, returning the contents of the file to the attacker.{{ ''.__class__.__mro__[1].__subclasses__()[133].__init__.func_globals.linecache.os.popen('id').read() }}
: This payload will execute theid
command on the server and return the result to the attacker.
Test it out with Akto! Check out Akto's test library on SSTI.
Here are three tests you can perform on SSTI using Akto:
Practical Demonstration of SSTI
Target: Portswigger SSTI Lab
Goal: To solve this lab, we have to execute an arbitrary code and delete a morale.txt file.
The application is a typical e-commerce website that displays products for users to order. Clicking on "view details" shows more information about a particular product. However, if a product is out of stock and you click on "view details", a message will appear on the screen.
As my proxy is on, I captured the requests in BurpSuite. Please take a look at the third request, which is a GET request with a "message" parameter that retrieves a message stating, "Unfortunately, this product is out of stock.”
This process can also be accomplished by directly modifying the URL in the browser. In this case, I used BurpSuite for better view of requests and responses.
The same message is reflected in the response.
Send the request to the repeater and analyze the request and response.
Exploitation
To test for SSTI vulnerability, we will try to inject a payload in the message parameter
Payload: <%= 7*7 %>
In this case, the code will be evaluated as 7*7
, resulting in the integer 49
.
In the ERB documentation, discover that the syntax <%= someExpression %>
is used to evaluate an expression and render the result on the page.
After sending the request, the response shows that the expression was evaluated by the server and the result is 49.
Now let’s try to execute an OS command on the server.
Payload: <%= system("rm /home/carlos/morale.txt") %>
The above payload will delete morale.txt file from the “carlos” account.
Don’t forget to URL encode the payload and send the request. Let’s go back to the application to check that the lab is solved!
Prevention
The best prevention is to never include user input in templates. Here are some other best practices to prevent SSTI:
The best strategy is to not allow users to submit or modify templates. Whenever possible, use string-like substitution instead of modifying the template itself. Do not concatenate user input with the template.
render( "Logged in as {name}", Map("name" => "Daniel") )
- Right!render( "Logged in as " + queryParam["name"] )
- Wrong!
Use logic-less templates - Template substitution should only perform a string replace without executing any code. These are also known as "logic-less" templates. A number of authors recommend using an engine like Mustache, which separates "appearance" from "logic".
By following these best practices, developers can reduce the risk of SSTI vulnerabilities and improve the overall security of their APIs.
Keep reading
API Security
3 minutes
What is API Discovery?
API Discovery helps identify, map, and manage APIs within an organization, ensuring security, performance, and seamless integration across systems.
API Security
5 minutes
Top 10 DAST Tools in 2024
DAST tools secure web apps by identifying vulnerabilities through automated security testing.
API Security
8 minutes
Security Information and Event Management (SIEM)
SIEM aggregates and analyzes security data across an organization to detect, monitor, and respond to potential threats in real time.
Experience enterprise-grade API Security solution