Server-side template injection (SSTI) is a vulnerability where a server uses an attacker’s input to render a template but fails to sanitize the content provided, enabling the attacker to inject scripts or other malicious artifacts, enabling XSS attacks or remote code execution (RCE) once the template is rendered. Below is a good introduction to SSTI from OWASP:
Templating engine discovery
There are various templating engines for web technologies, some examples are:
Templating engine | Language | Server / client side |
---|---|---|
Twig | PHP | Server side |
Freemarker | Java | Server side |
Pug / Jade | JavaScript | Server side |
Jinja | Python | Server side |
Handlebars | JavaScript | Both |
Mustache | Multiple | Varies |
Knowing what template engine we’re targeting is pivotal to successful exploitation. To discover the templating engine for a target we suspect is vulnerable to SSTI, follow their documentation and attempt to use engine-specific syntax to discover the target’s templating engine.
Code execution with Twig
Some features of Twig enable attackers to gain RCE on PHP servers using SSTI.
Using filters that take functions as arguments, we can provide system
as a
function, and then our argument can be some bash
command that will be executed
on the host via PHP. For example, we use the
reduce
filter to read
files on the host:
{{ [0]|reduce('system', 'cat /etc/passwd') }}
Code execution with Freemarker
Apache Freemarker is a templating engine commonly paired with Java applications. If an attacker can provide arbitrary input to a server rendering Apache Freemarker templates, attackers can gain RCE, e.g.:
${"freemarker.template.utility.Execute"?new()("cat /etc/passwd")}
Code execution with Pug
Pug is a templating engine for JavaScript and NodeJS, enabling the rendering
of templates both on the client and server side. Pug is used to inject and
generate HTML tags and content. Attackers can gain RCE on a NodeJS server
rendering Pug templates by abusing the client_process.spawnSync
method, e.g.:
- var require = global.process.mainModule.require
= exec = require('child_process').spawnSync('cat', ['/etc/passwd']).stdout
Leaking sensitive information from Jinja
Jinja is a templating engine for Python, primarily used for server-side rendering. Attackers can use template injection attacks to disclose sensitive information about a web application’s configuration, e.g.:
{{ config | pprint}}
The above Jinja template leaks the global Flask config
value for the Jinja
templating engine, and pretty prints the contents using the pprint
filter.