Skip to main content

Server side template injection

Need

Prevention of server-side template injection vulnerabilities

Context

  • Usage of Java for building cross-platform applications and enterprise-level software
  • Usage of javax.servlet for building Java web applications with servlets
  • Usage of java.io for input and output operations in Java

Description

Non compliant code

import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;

public class TemplateServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String name = request.getParameter("name");
String template = "Hello, " + name;
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println(template);
}
}

The above code is an example of a Servlet in a Java web application that takes a request parameter "name" and includes it in a server-side template string, which is then output to the client.

This is vulnerable to Server Side Template Injection (SSTI) because the user-supplied input ("name" parameter) is directly included in the server-side template without any sanitization or escaping.

An attacker could exploit this by sending a specially crafted request with a "name" parameter that includes template syntax. For example, an attacker could send a request with a "name" parameter of ${7*7}. The server-side template would then evaluate this expression, and the response would include "Hello, 49" instead of "Hello, $49".

This is a simple example, but in a real-world application, an attacker could potentially include more complex expressions that could execute arbitrary code on the server, access sensitive data, or perform other malicious actions.

Steps

  • Sanitize user input: Validate and sanitize any user input before using it in the template. This can be done by using input validation techniques and encoding/escaping user input.
  • Use a secure template engine: Instead of concatenating user input directly into the template, use a secure template engine that automatically escapes user input to prevent template injection.
  • Implement a whitelist approach: Define a whitelist of allowed characters or patterns that can be used in the template. Reject any input that does not match the whitelist.
  • Limit template functionality: Restrict the capabilities of the template engine to only allow necessary and safe operations. Disable or remove any unnecessary template features that could be exploited.
  • Keep templates separate from code: Store templates in separate files instead of embedding them directly in the code. This allows for easier maintenance and reduces the risk of injection vulnerabilities.
  • Regularly update and patch dependencies: Keep all dependencies, including the template engine, up to date with the latest security patches to mitigate any known vulnerabilities.
  • Implement strong access controls: Ensure that only authorized users have access to the template engine and the ability to modify templates.
  • Perform security testing: Regularly conduct security testing, including penetration testing and code reviews, to identify and fix any potential vulnerabilities in the application.

Compliant code

import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import org.owasp.encoder.Encode;

public class TemplateServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String name = request.getParameter("name");
// Sanitize user input
String sanitized_name = Encode.forHtml(name);
String template = "Hello, " + sanitized_name;
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println(template);
}
}

The original code was vulnerable to Server Side Template Injection (SSTI) because it directly used user input in a server-side template without any sanitization or validation. This could allow an attacker to inject malicious payloads into the template, which would then be executed on the server side.

The fixed code mitigates this vulnerability by sanitizing the user input before using it in the template. This is done using the OWASP Java Encoder library, which provides a set of methods for encoding user input to prevent various types of injection attacks, including SSTI.

In the fixed code, the Encode.forHtml(name) method is used to encode the user input for use in an HTML context. This method encodes special characters that have significance in HTML, such as <, >, &, #, and ;, into their corresponding HTML entities. This prevents these characters from being interpreted as part of the HTML markup, effectively preventing SSTI.

In addition to sanitizing user input, it's also recommended to follow the other steps mentioned earlier to further secure the application against SSTI and other types of vulnerabilities. These include using a secure template engine, implementing a whitelist approach, limiting template functionality, keeping templates separate from code, regularly updating and patching dependencies, implementing strong access controls, and performing regular security testing.

References