Confirming SSTI
Inject the universal test string to provoke a syntax error in any popular template engine:Identifying the Template Engine
Inject arithmetic payloads and follow the response to narrow down the engine.
Start with
${7*7}. If not executed, try {{7*7}}. If that executes, try {{7*'7'}} to tell Jinja2 (repeats the string) from Twig (returns 49).
Jinja2
Jinja2 is used in Python web frameworks (Flask, Django). Any library already imported by the application is accessible in payloads.Information Disclosure
Local File Read
Remote Code Execution
os is not already imported, __import__ handles it inline.
Twig
Twig is the template engine for PHP. The_self keyword exposes limited internal information.
Information Disclosure
Local File Read
Twig itself has no file-read function, but Symfony’sfile_excerpt filter exposes one:
Remote Code Execution
filter() passes the array element as an argument to the named PHP function.
Handlebars
Handlebars is a JavaScript template engine common in Node.js applications. It has a sandbox, butthis.constructor.constructor exposes the native Function constructor, which evaluates arbitrary JavaScript strings and breaks out of the sandbox entirely.
Confirming SSTI
[object Object] or a function reference rather than the raw string, Handlebars is rendering the input.
Remote Code Execution
Use#with to shift context to the Function constructor, then call it with a JavaScript string to execute:
process.env to confirm code execution before running commands:
The payload works because Handlebars’
#with helper shifts the block context to whatever value is passed. Passing the result of Function('return ...')() executes arbitrary JS and makes the result the new context, which is then printed with {{this}}.