Research by Erez Goldberg
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:
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.
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.
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:
os.popen()
function to execute the sleep command for 10 seconds.sleep
command, causing a delay in the server’s response.Execute utility
class in Freemarker, which allows the execution of system commands.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.
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.
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:
If the server is vulnerable to SSTI, it executes the payload and sends a request to the Interactsh
server:
The Interactsh server captures these interactions and notifies the attacker, confirming that the payload execution occurred.
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:
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:
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:
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:
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:
php -r
command to run PHP code directly without the need to create a PHP file.$d
to the base64-encoded
string RmFsc2U
.$d
using the base64_decode
built-in PHP function.RmFsc2U
is the base64 encoding of the word False
.eval("return (False) && sleep(4);");
sleep(4)
should be executed.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.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
:
Decoding the obfuscated payload step-by-step:
id
is constructed using Character.toString
and its corresponding ASCII value.T(java.lang.Character).toString(105)
constructs the character i
.T(java.lang.Character).toString(100)
constructs the character d
.id
using the concat method to form the complete command string.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:
When converting each value to characters, we get the following payload:
Eventually, the decoded Base64 string reveals a reverse shell command:
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:
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:
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:
The decoded data executed by the server is:
The downloaded file is a shell script dropper, with the miner’s wallet:
c3pool.org is a cryptocurrency mining pool:
The 0dzFrRzQ.sh
dropper executes additional commands on the server and downloads an ELF executable file based on the victim’s architecture:
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:
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:
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.
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’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