Web applications play a vital role in delivering dynamic content to users. To achieve this, developers often utilize server-side templates, which provide a powerful and consistent way to generate dynamic web pages. However, along with this power comes the risk of Server-Side Template Injection (SSTI), a vulnerability that can have serious consequences if left unaddressed. So let's explore what server-side templates are, how the SSTI vulnerability occurs, and how developers and penetration testers can detect and mitigate this flaw.
Server-Side Templates: Separating Logic from Presentation
Server-side templates are tools that allow developers to separate the presentation logic from the underlying application code. These templates typically consist of a combination of static content and placeholders (variables or expressions) that dynamically get replaced with actual values when the page is requested. This allows developers to create reusable components, maintain consistency, and enhance the efficiency of web application development since they can focus on the content of the pages instead of how the page is laid out.
Understanding SSTI Vulnerability
Server-Side Template Injection occurs when user-supplied input is improperly used within a template context. If an attacker can inject malicious template code into a server-side template, leading to its execution on the server, the application is vulnerable to SSTI. The consequences of SSTI can be severe, ranging from data leakage and unauthorized access to remote code execution.
Identifying the SSTI Flaw
As a penetration tester, detecting SSTI vulnerabilities requires a process for identifying potential injection points. While this is a standard process, we need to ensure that it accounts for the payloads that discover and exploit the SSTI issue. The following techniques can help in this process:
Input Validation: Review the web application for any user-supplied input that is directly or indirectly used within what appears to be a template. Basically, the tester needs to keep in mind parameters and input used during mapping that appear to be reflected back to the user as part of the page. This should sound familiar as this is also how we find Cross-Site Scripting issues. Which means, in most cases, the tester can expand the payloads they use for finding XSS to include this other form of injection.
Context Awareness: Understand the template engine being used and its specific syntax. As with XSS, we are injecting client-side code. With SSTI we are injecting payloads that contain code that is used by the template engine, not the browser. Different template engines may have different ways of handling expressions and variable interpolation. This does require the tester to try and determine which template engine is being used. Different payloads can help with this, but recon and other technology detection techniques can also help.
Manual Testing and Fuzzing: The next step in the process is actually testing the application and its parameters for this flaw. As stated above, this is easily done by expanding the XSS detection techniques to include SSTI payloads. Personally, I do this both when manually entering data in the target application as well as when fuzzing multiple payloads into different fields. Some basic payloads I use are outlined below.
Payload Examples
To assist developers in building unit test cases and penetration testers in finding these types of flaws, let's talk about some payloads that can find and exploit this vulnerability.
- Simple Expression Injection:
This payload is the primary discovery payload, similar to <script>alert(“XSS”)</script> in XSS discovery. Consider a template expression that retrieves a user's name from a database and displays it on a web page. An attacker could attempt to inject arbitrary template code by injecting into the input field, like so:
42
If the template engine evaluates this expression within the template context, the result would be `42`. If it doesn’t, the response would include 42
instead.
It is important to note that the specific payload syntax, responses from the server, and other capabilities may vary depending on the template engine being used. Different template engines have their own syntax and mechanisms for evaluating expressions and executing code / commands within the template context. Therefore, understanding the template engine's documentation and syntax is crucial when crafting SSTI payloads for testing and exploitation purposes. For example, the response could be HTML encoded or the returned data could be some other interpretation of the payload such as `21, 21`. The defining characteristic is that the returned data is not just characters entered as the payload, just like testing for XSS.
If the simple injection works, now it is time to start determining how the template engine might be exploited in other attacks.
- File Access:
One thing to test for is if the flaw allows for file access on the server. Some template engines allow accessing files via the engine. Attackers may exploit this functionality to gain unauthorized access or retrieve sensitive information. For example, on a Unix target, we could replace the simple injection with a new value:
This payload attempts to read the `/etc/passwd` file on the server and display its contents within the response. By testing such payloads, developers can identify if file access is improperly allowed within their templates.
- Code Execution:
The final payload we will discuss is code execution. This, of course, is often the ultimate target for a tester as it allows so much more than just reading files. For instance, consider the following payload:
In this case, the payload attempts to execute the `ls -l /` command via the python os.system function, which is a command that lists the files and directories in the root directory. If the template engine does not properly mitigate SSTI vulnerabilities, this payload could result in the execution of the command on the server.
Protecting Against SSTI Vulnerabilities
Developers can take proactive measures to prevent SSTI vulnerabilities. Here are a few key practices to follow:
Input Sanitization: Thoroughly validate and sanitize user input to prevent any unauthorized template code execution. Apply strict input validation and ensure that user-supplied data is escaped or properly rendered within the template. If you are using allow-lists on input, this type of attack should already be blocked.
Secure Configuration: Configure the template engine to run in a sandboxed environment with restricted permissions. Limit access to sensitive resources and disable features that are not required.
Least Privilege Principle: Ensure that the application's server-side rendering process runs with the least privileged user account. This helps mitigate the potential impact of an SSTI attack.
Server-Side Template Injection (SSTI) is a significant vulnerability that developers need to be aware of when working with server-side templates. By understanding the potential risks, applying secure coding practices, and conducting thorough testing, developers can protect their applications against this vulnerability. Regular security audits, including penetration testing, can help identify and address SSTI vulnerabilities early on, ensuring the integrity and security of web applications. By utilizing payloads during testing, developers can build robust unit test cases and prevent SSTI vulnerabilities from compromising their web applications.