Exploring the dangers of server-side template injection

With the ever-growing list of web technologies, developers must always be on the lookout for new vulnerabilities. In recent years one such technology which seems to be gathering pace is templates. Whether you're building with Python, PHP or even Go, the list of templating engines seems to be increasing by the day.

So, what exactly is a templating engine? A templating engine takes static data, often stored in another file, and returns the contents. At runtime, any placeholder variables will be substituted for their values.

By this point, you're probably wondering what a placeholder is. Depending on the templating engine used on the web application, you'll often see that template files include variables by using one of the following markers, although others are available.

<%= ... %>  -  ERB
{{ ... }}  -  Jinja
#{ ... }   -  Pug
${ ... }   -  Mako

Similar to cross site scripting, this vulnerability exists when user-provided information is supplied without sufficient sanitation. However, the difference here is that the provided information is passed to a back-end templating engine which can often interpret provided information in an unexpected way. Here's an example, let's say our bookstore website is built with Python and makes use of the Mako templating engine. When a user searches for their favourite book the title of the page includes their search term. 

From the example we've given, we know that the web application uses the Mako templating engine. As you can see above, we know that Mako will include a variable by making use of the ${ ... } placeholder, so what happens if a user were to search for something while using this placeholder? Well, assuming their search term has the correct programming syntax, any code inside ${ ... } would be executed.

Testing for server-side template injection

Testing for server-side template injection is actually a lot simpler than you might think, by performing a simple mathematical test within the ${ ... } we are able to determine whether our code is being executed, one such example would be ${ 7*7 }. If successful, the page would show 49 within the title. It's important to note, some placeholders are also recognised by front-end JavaScript libraries such as Angular, this would actually be a cross site scripting vulnerability.

Depending on the templating engine in use would depend on which placeholder is required, simply testing these within the web application search field would reveal the correct templating engine.

What can be achieved with server-side template injection

Due to the fact server-side template injection allows for code to be executed on the application back-end, this vulnerability has the potential to completely compromise the web server. In the example above, we are using the Mako templating engine which runs using Python. A simple line of code will allow us to read the full source code of the application in question. I have provided a line of code below, this line is very simple and assuming we already know the application filename it would grant full transparency regarding the application in question.

open("app.py").read()

But what happens if the application isn't built with Python? Well, very little actually changes. The malicious user would simply have to alter the syntax of the injected code and they would achieve the same result, here's a Ruby/ERB example.

File.open("app.rb").read

Protecting against server-side template injection

Templates should not be rendered using user-supplied input, instead, they should make use of template parameters. At the very least, sanitization should always be performed and dangerous characters should always be removed or converted into their HTML representation (HTML entity).

Assuming that the preventative options provided would not match your use case, you could always make use of a sandbox. A sandbox is a secure container or "docker" that the application can run inside, any code or operations performed by the web application would be restricted to the permissions set out in the sandbox, which would limit the attacker's options.

Make a suggestion +

Notice something not quite right? That's fine we're not perfect. Why not make a suggestion on our community forum, you should be able to see the correct formatting below.

Page Title:
Suggestion/Improvement:
Make suggestion

Still need help?

Are you having trouble using arctil? Why not try reaching out to our Community Forum.

Alternatively, you can try contacting us through the Contact page.