Server-Side Template Injection: Transforming Web Applications from Assets to Liabilities

Executive Summary

Server-Side Template Injection (SSTI) vulnerabilities refer to weaknesses in web applications which attackers can exploit to inject malicious code into server-side templates. This allows them to execute arbitrary commands on the server, potentially leading to unauthorized data access, server compromise, or exploitation of additional vulnerabilities.

Recently, SSTI vulnerabilities are becoming increasingly prevalent and concerning with a notable increase in critical CVEs affecting various web applications. These vulnerabilities are particularly dangerous because they can be exploited remotely and allow attackers to gain control over servers hosting these applications.

Key Risks of SSTI:

  • Arbitrary Code Execution: Attackers can gain full control over the server, leading to a complete system compromise.
  • Data Theft: Sensitive business information, user data, and configuration files can be accessed and stolen.
  • Reputation Damage: Data breaches can erode customer trust and lead to legal and regulatory consequences.

Over the last year, high-profile platforms such as Atlassian Confluence, CrushFTP, and Rejetto HTTP File Server were specifically targeted and successfully exploited in real-world attacks. CISA (The Cybersecurity and Infrastructure Security Agency) highlighted incidents where these platforms were compromised due to SSTI vulnerabilities. This emphasizes how critical the issue is and the potential impact on organizations relying on these widely-used software solutions.

Over the past three months, on average, one out of every 16 organizations were impacted weekly by Server-Side Template Injection (SSTI) attacks.

During this period, the Retail/Wholesale sector saw the highest impact, with these attacks affecting on average one out of every 11 organizations weekly. The Retail/Wholesale sector is particularly vulnerable to these attacks due to the high transaction volumes with valuable customer data which includes personal information and payment details attractive to hackers, integration with third-party e-commerce services expanding the attack surface, reliance on outdated legacy systems and public facing applications.

Following closely was the Finance/Banking sector, where incidents were reported in 1 out of 15 organizations. Usually targeted for their sensitive financial data and access to finance, financial institutions are also attractive targets for State-Sponsored and organized cybercrime attacks. Further attacks are also fueled by the widespread adoption of online and mobile banking services, due to increased attack surfaces, increasing the potential for exploitable vulnerabilities. Financial institutions often rely on third-party services and APIs, which can introduce additional security risks if not properly managed as does reliance on legacy systems and complex IT systems.

In terms of infrastructure, cloud-based organizations face approximately 30% more frequent attacks on a weekly basis compared to their on-premises counterparts. Whilst SSTI attacks do not occur only on Cloud-based infrastructure, SSTI may take place more frequentl in cloud environments due to complexity of the technology or misconfigurations, third-party integrations or security coverage gaps between the cloud provider and the customer.

Addressing SSTI vulnerabilities is a critical priority for organizations involved in web application development and maintenance, especially as there is widespread use of template engines and the common need for dynamic content generation based on user input. It requires robust security practices, including secure coding techniques, regular vulnerability assessments, and prompt patching of software to mitigate these risks effectively.

In this blog, we explore real-world examples of SSTI exploits, ranging from simple scans to malware downloads and exploits demonstrating hackers gaining complete control over the vulnerable system.

What is Server-Side Template Injection Vulnerability

A Server-Side Template Injection (SSTI) vulnerability occurs when a user input is improperly handled and injected into a web application’s template engine. Template engines are used to dynamically generate HTML content by combining templates with data.
An attacker can use this vulnerability to inject malicious code into the templates. Once executed on the server, this code can potentially lead to control over the affected server environment. Attackers can then access sensitive information, execute arbitrary commands, and exploit other vulnerabilities within the application.

SSTI can affect various template engines such as Jinja2 for Python, Freemarker for Java, and Twig for PHP, making it a widespread concern across different programming environments. 

To understand the severity and practical implications of SSTI related vulnerabilities, let’s explore real-world examples of SSTI exploits.
These instances highlight how attackers are leveraging this vulnerability class to compromise systems and extract sensitive information from vulnerable systems.

Real-World Examples of SSTI Exploits

Fuzzing is a popular technique among security testers to detect vulnerabilities by automatically injecting a wide range of inputs into an application and observing its behavior. 
In the context of SSTI, fuzzing involves sending various payloads to different parts of a web application to determine if and where user inputs are being processed by a template engine by observing the differences in results returned in the server’s responses.
Fuzzing is the primary method used to identify the specific type of template engine in use, which is essential for crafting effective payloads tailored to that engine’s syntax and behavior. 

Blind SSTI is a subset of this technique and a common approach when testing for SSTI vulnerabilities in template engines.
Unlike regular SSTI, where the output of injected code can be directly observed in the response, blind SSTI does not provide immediate feedback through the application’s output. Instead, it relies on indirect methods to confirm that the injection is successful and to gather information.

One particularly disruptive way to exploit SSTI is to utilize the sleep function.
During the fuzzing phase of SSTI vulnerability assessment, sleep serves as a crucial tool for validation, timing analysis, and stealth. It helps testers confirm the presence of vulnerabilities and gather information about the target environment in a non-destructive manner. Attackers often use sleep commands to measure the time it takes for the server to respond to various inputs.

Here are in-the-wild examples involving sleep functions in different template engines:

  • In the following example, by traversing the internal objects within Jinja2, the payload uses Python’s os.popen() function to execute the sleep command for 10 seconds.
Figure 1: Jinja2 SSTI payload leverages template context manipulation.
  • Another Python payload leverages built-in classes and methods to execute the sleep command, causing a delay in the server’s response.
Figure 2: Payload utilizing the Method Resolution Order (MRO) to access specific attributes and methods of objects.
  • The next Java payload creates a new instance of the Execute utility class in Freemarker, which allows the execution of system commands.
Figure 3: Payload exploits FreeMarker’s template processing to execute arbitrary commands.
  • In the example below, we can see a delay of 10 seconds in the response, which indicates a vulnerable server:
Figure 4: HTTP request and response of SSTI payload demonstrating time delay measurement.

Another technique used by attackers is employing nslookup in SSTI payloads to detect blind SSTI. By injecting a payload that triggers a DNS query to a controlled domain, an attacker can confirm that the server is vulnerable to SSTI and execute arbitrary commands on the server.

This method allows attackers to bypass traditional network security measures, as DNS queries are often less scrutinized than HTTP traffic.
In the following Python example, the payload is rendered in a Jinja2 template. It attempts to execute the nslookup command which triggers a DNS lookups query or an HTTP request to an attacker-controlled server. 

Figure 5: Payload accessing global variables to execute the nslookup OS command.


An attacker sends many requests to potentially vulnerable servers but only the vulnerable ones will ping back. Using this technique, attackers can easily filter out the vulnerable systems.

Next, in Java, attackers use RMI (Remote Method Invocation) Lookup which allows a Java program to connect to and use another computer’s objects.

Figure 6: Payload uses Java RMI (Remote Method Invocation) service to invoke methods remotely on objects.

Attackers can craft and test various SSTI payloads in a controlled environment prior to deploying them against a real target by creating HTTP request-response pairs that simulate web server interactions.
Interactsh is one of the tools used to create the HTTP pairs. It is designed to help security researchers and penetration testers detect out-of-band (OOB) interactions, as shown in the following image:

Figure 7: HTTP request with SSTI payload using nslookup with a randomly generated subdomain created by Interactsh.

If the server is vulnerable to SSTI, it executes the payload and sends a request to the Interactsh server:

Figure 8: On the attacker’s side, you can see incoming requests of DNS interactions from vulnerable servers.

The Interactsh server captures these interactions and notifies the attacker, confirming that the payload execution occurred.

SSTI Obfuscation Techniques

Attackers often use obfuscation to evade detection by security mechanisms and increase the likelihood of successfully exploiting vulnerabilities.
By altering the structure or appearance of the payload, a malicious payload can go undetected by input validation or filtering mechanisms implemented by web applications.

One popular approach is base64 encode functions. By encoding a malicious payload using Base64, attackers try to evade detection by intrusion detection systems and web application firewalls, as the encoded payload doesn’t contain any clearly visible indicators and looks like a random blob of characters.

When the server receives the HTTP request containing the injected payload, it decodes the base64-encoded data to retrieve the original payload. The decoding process typically occurs within the template engine itself rather than the CLI.
Using built-in functions, the template engine can retrieve the original command or instructions, which are then executed in the shell environment.

In the following example, an attacker exploits CVE-2022-22954 to inject a Java payload into an expression with an encoded string of data passing as an argument to the eval function:

Figure 9: Java SSTI payload attempts to exploit a known vulnerability.

The string decodes to the following command:  cat /etc/passwd

Web applications typically do not store user credentials in the /etc/passwd file but instead store user information, including credentials, in a database specific to the application.

However, this attack could be adapted to leak other potentially sensitive files about the system or the app and in launching further attacks.

In the following payload, a decoded payload is submitted to the Java exec command:

Figure 10: Apache Velocity template payload attempts to execute bash command of a base64 decoded string.

The string is decoded to the following command:

In the next example of CVE-2024-28254, we encounter a payload that uses a multi-step execution process. The technique illustrates how attackers leverage nested layers of base64 encoded payloads:

Figure 11: Java payload using a built-in class to decode data.

After the initial decoded payload, a second layer of base64 encoded payload is revealed embedded within the first decoded string:

When the second decoded string runs, it exposes the final payload which is a reverse shell command in its original form:

This payload enables the attacker to take control of the victim’s system.

Attackers may craft nested layers of base64 encoding technique as a strategy to obscure malicious intent during runtime and evade initial detection by security systems.

In the example below, attackers use base64 encoded payloads in PHP implementation:

Figure 12: PHP payload abuses the Twig template engine to register and execute arbitrary commands.

The payload registers the callback function exec, which afterwards makes the subsequent call to getFilter. Thisleads to the execution of commands on the underlying operating system and environment.

In the decoded payload we can see a combination of several techniques:

The payload performs the following actions:

  • Uses the php -r command to run PHP code directly without the need to create a PHP file.
  • Sets the variable $d to the base64-encoded string RmFsc2U.
  • Attempts to decode $d using the base64_decode built-in PHP function.
    The string RmFsc2U is the base64 encoding of the word False.
  • After decoding, the eval statement becomes eval("return (False) && sleep(4);");
    This statement evaluates the decoded string and uses its boolean value to determine if sleep(4) should be executed.
  • Despite the decoded string being False, the boolean evaluation in PHP considers it true (because it’s a non-empty string), and as a result, sleep(4) will be executed in this payload.

Character Concatenation Obfuscation

Another advanced obfuscation technique is Java character concatenation. This involves dynamically constructing strings by concatenating individual characters using functions like Character.toString.
The attacker obfuscates the payload and makes it harder for pattern-based security mechanisms to detect the malicious code. The technique constructs parts of an SSTI payload dynamically at runtime by converting numerical values to characters and concatenating them.

In the example below, T(java.lang.Character).tostring(105)T(java.lang.Character).tostring(100) is decoded to id:

Figure 13: Using the toString method to obfuscate SSTI payloads.

Decoding the obfuscated payload step-by-step:

  1. Each character in the string id is constructed using Character.toString and its corresponding ASCII value.
  2. T(java.lang.Character).toString(105) constructs the character i.
  3. T(java.lang.Character).toString(100) constructs the character d.
  4. The characters are concatenated into the string id using the concat method to form the complete command string.
  5. The constructed id command string is passed to Runtime.getRuntime().exec function, and its output is read using IOUtils.toString.

The final payload is:
T(java.lang.Runtime).getRuntime().exec(id)

In this way, the attacker can obfuscate an entire payload and not just the detectable commands, as can be seen in CVE-2016-4977 example:

Figure 14: Leveraging the toString() and concat() methods to create the payload dynamically.

When converting each value to characters, we get the following payload:

Eventually, the decoded Base64 string reveals a reverse shell command:

Advanced Scenario: SSTI Cryptojacking

SSTI vulnerabilities are exploited in several types of real-world attacks. A common advanced attack scenario leverages SSTI vulnerabilities to covertly mine cryptocurrency using the compromised server’s resources.

Before attackers fully exploit a template engine server, they typically perform some fuzzing technique or exploit the SSTI vulnerability to identify whether the server is vulnerable and to what extent.

In the following in-the-wild attack use-case, the attackers performed SSTI vulnerability testing on a target:

Figure 15: Fuzzing the target with initial Java SSTI payload.

The payload decodes into the ping command:

dnslog.cn is a service used to detect and capture DNS-based interactions. It is commonly utilized in security research and penetration testing to identify and exploit vulnerabilities that involve external DNS requests. As we saw with interactsh, this is used for a similar purpose and has similar functionality.

Following the actions with the previous payload, the attackers perform another test on the potentially vulnerable system:

Figure 16: Additional Java SSTI payload during the fuzzing phase.

The payload decodes into the curl command:

After the two successful tests, the attackers use an SSTI payload to inject a command that downloads a malicious file from the attackers’ domain:

Figure 17: Cryptojacking deployment via an SSTI payload.

The decoded data executed by the server is:

The downloaded file is a shell script dropper, with the miner’s wallet:

Figure 18: code snippet of the dropper with the miner’s wallet in clear text.

c3pool.org is a cryptocurrency mining pool:

Figure 19: c3pool.org website offers a platform for miners to pool their resources to mine Monero.

The 0dzFrRzQ.sh dropper executes additional commands on the server and downloads an ELF executable file based on the victim’s architecture:

Figure 20: The script tries to download and save the file in the tmp folder.

The .Font-unix executable is revealed as a known crypto-miner whose aim is to monetize the victim’s resources.

Tracing the wallet via c3pool website, we can follow the victims in the miner list:

Figure 21: Various metrics and statistics are used to measure and manage the performance of the victims’ mining.

Infection Chain

Cryptojacking SSTI in Windows OS:

Template engines are cross-platform, meaning they can be used on different operating systems such as Linux and Windows.
Therefore, the payloads must be tailored to perform OS-specific operations.
In the following example, an attacker injects a PowerShell command into the exec function:

Figure 22: Leveraging SSTI to execute a PowerShell encoded command.

The decoded payload reveals a PowerShell download cradle:

The wi.txt file is fetched from a remote machine and injected directly to the memory of the PowerShell process for execution.

This method leverages in-memory execution, enhancing its ability to evade detection while executing potentially malicious PowerShell scripts.
The file is a PowerShell script dropper utilizing Windows Management Instrumentation (WMI) and involves multiple tactics including, log deletion, persistence, removing known competitive miners and downloading the executable miner.

Conclusion

Server-Side Template Injection (SSTI) is a critical vulnerability that can lead to and according to CISA, had led to severe security breaches if not properly mitigated.
By exploiting SSTI, attackers can execute arbitrary code on the affected server, access sensitive data, and even gain full control of the server environment.
This vulnerability is particularly dangerous as it leverages the capabilities of template engines which are designed to process, evaluate, and execute code during server-side rendering, making exploitation both powerful and versatile.

Fuzzing, including techniques like blind SSTI, plays a crucial role in identifying potential vulnerable systems, vulnerabilities, and the specific type of the server-side template engine that was used.
Blind SSTI involves sending payloads without immediate visible output, but the result can be inferred from indirect indicators such as timing differences or out-of-band techniques. 
This information is essential for crafting suitable payloads to exploit the vulnerabilities of that particular engine.

In practice, attackers use various obfuscation techniques, such as encoding payloads in base64 or by using tostring methods, to bypass input validation and detection of traditional mechanisms.

Advanced exploitation use-cases can include crypto-jacking, where attackers use SSTI to inject scripts that download and execute crypto-mining executables using the resources of the affected system.  

Check Point Customers Remain Protected

Check Point’s Intrusion Prevention Systems blocks attempts to exploit weaknesses in vulnerable systems or applications, protecting users in the race to exploit the latest breaking threat. Check Point IPS protections in our Next Generation Firewall are updated automatically. Whether the vulnerability was released years ago, or a few minutes ago, Check Point customers remain protected from such weaknesses from these vulnerable systems in your organization.

IPS Protections:

Python Server-Side Template Injection

Java Server-Side Template Injection

PHP Server-Side Template Injection

Ruby Server-Side Template Injection

Node.js Server-Side Template Injection

Expression Language Server-Side Template Injection

The post Server-Side Template Injection: Transforming Web Applications from Assets to Liabilities appeared first on Check Point Research.

Article Link: Server-Side Template Injection: Transforming Web Applications from Assets to Liabilities - Check Point Research