Server side template injection of Web Security

Time:2021-3-30

Server-side template injection

In this section, we will introduce what is server-side template injection, outline the basic methods to exploit this vulnerability, and also provide some suggestions to avoid this vulnerability.

What is server side template injection

Server side template injection means that the attacker can inject malicious load into the template by using the syntax of the template itself, and then execute it on the server side.

The template engine is designed to generate web pages by combining fixed templates and variable data. When user input is directly spliced into the template instead of being passed in as data, the server-side template injection attack may occur. This allows the attacker to inject arbitrary template instructions to manipulate the template engine, so that he can completely control the server. As the name suggests, server-side template injection payloads are delivered and executed on the server side, which may make them more dangerous than typical client-side template injection.

What is the impact of template injection on the server

The server-side template injection vulnerability will make the website face a variety of attacks, depending on the template engine discussed and how the application uses it. In rare cases, these vulnerabilities do not pose a real security risk. However, in most cases, the impact of server-side template injection can be catastrophic.

In the most serious case, it is possible for an attacker to complete remote code execution, thus taking full control of the back-end server and using it to carry out other attacks on the internal infrastructure.

Even if it is impossible to execute the remote code completely, the attacker can still use the server-side template injection as the basis of many other attacks, which may gain access to sensitive data and arbitrary files on the server.

How does the template injection vulnerability on the server come into being

When user input is directly spliced into the template instead of being passed in as data, the server-side template injection vulnerability will appear.

Static templates that simply provide placeholders and present dynamic content in them are usually not attacked by server-side template injection. A typical example is to extract a user name as the beginning of an email, such as the following extracted from a twig template:

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

This is not easy to be attacked by template injection on the server side, because the user’s name is only passed to the template as data.

However, web developers may sometimes connect user input directly to the template, such as:

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

Instead of passing static values to the template, get name is used to dynamically generate a part of the template itself. Since the template syntax is executed on the server, it may allow an attacker to use the name parameter as follows:

http://vulnerable-website.com/?name={{bad-stuff-here}}

Loopholes like this are sometimes caused by people who are not familiar with security concepts designing defective templates. As in the above example, you may see different components, some of which contain user input, connect and embed into the template. In some ways, this is similar to the SQL injection vulnerability, which is the improper statement.

Sometimes, however, this behavior is actually intentional. For example, some websites intentionally allow privileged users (such as content editors) to edit or submit custom templates by design. If the attacker can take advantage of the privileged account, it will obviously bring huge security risks.

Constructing template injection attack on server

The following abstract process is usually involved in identifying the server template injection vulnerability and planning a successful attack.

Server side template injection of Web Security

probe

Server side template injection vulnerabilities are often overlooked, not because they are complex, but because they are only really obvious in front of the auditors who explicitly look for them. If you can detect a vulnerability, it will be very easy to exploit it. This is especially true in non sandbox environments.

Like any vulnerability, the first step to exploit it is to find it first. Perhaps the simplest initial method is to inject a series of special characters commonly used in template expressions, such as${{<%[%'"}}%\To try to blur the template. If an exception is thrown, it indicates that the server may have interpreted the injected template syntax in some way, which indicates that there may be a vulnerability in the server-side template injection.

The template injection vulnerability of server occurs in two different contexts, and each context needs its own detection method. Regardless of the outcome of the obfuscation attempt, try the following context specific methods. If fuzziness is uncertain, then using one of these methods, the vulnerability may be exposed. Even if obfuscation does indicate a template injection vulnerability, you still need to determine its context to exploit it.

Plaintext context

Plain text context.

Most template languages allow you to freely enter content by directly using HTML tags or template syntax. The back end will render the content as HTML before sending the HTTP response. For example, in the FreeMarker template,render('Hello ' + username)May render asHello Carlos

This is often mistaken as a simple XSS vulnerability and used for XSS attacks. However, by setting the mathematical operation as the value of the parameter, we can test whether it is also the potential attack point of the server template injection attack.

For example, consider including the following template code:

render('Hello ' + username)

During the review process, we can test the server template injection by requesting the following URL:

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

If the result output containsHello 49This indicates that the mathematical operation has been executed by the server. This is a good proof of the server-side template injection vulnerability.

Note that the specific syntax required to successfully compute mathematical operations will vary depending on the template engine used. We’ll explain it in detail in the identify step.

Code context

Code context.

In other cases, the vulnerability is exposed by placing user input in a template expression, as seen in the email example above. This can take the form of placing variable names that can be controlled by users in parameters, for example:

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

The URL generated on the website is similar to:

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

The output of the rendering may beHello Carlos

It’s easy to ignore this context in the evaluation process because it doesn’t produce an obvious XSS and is almost the same as a simple HashMap lookup. In this case, one way to test the server template injection is to first inject arbitrary HTML into the value to determine that the parameter does not contain a direct XSS vulnerability

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

In the absence of XSS, this usually results in white space (Hello only, no username), coded tags, or error messages in the output. The next step is to try to use the generic template syntax to jump out of the statement and try to inject any HTML after it:

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

If this leads to errors or blank output again, you are using the wrong template syntax. Or, the syntax of the template style is invalid, so the server-side template injection cannot be performed. If the output is presented correctly with arbitrary HTML, this is the key proof of the existence of the template injection vulnerability on the server

Hello Carlos<tag>

distinguish

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

Although there are a large number of template languages, many use very similar syntax, which is specifically chosen to avoid conflicts with HTML characters. Therefore, it may be relatively easy to construct a trial payload to test which template engine is being used.

It’s enough to simply submit invalid syntax, because the generated error message will tell you which template engine you used, and sometimes even which version. For example, illegal expression<%=foobar%>The following response of ruby based Erb engine is triggered:

(erb):1:in `<main>': undefined local variable or method `foobar' for main:Object (NameError)
from /usr/lib/ruby/2.5.0/erb.rb:876:in `eval'
from /usr/lib/ruby/2.5.0/erb.rb:876:in `result'
from -e:4:in `<main>'

Otherwise, you will need to manually test different language specific payloads and study how the template engine interprets them. With an exclusion process based on whether the syntax is valid or invalid, you can narrow the range of options faster than you think. A common approach is to inject arbitrary mathematical operations using syntax from different template engines. Then, observe if they are executed successfully. To complete this process, you can use a decision tree similar to the following:
Server side template injection of Web Security

You should note that the same payload can sometimes get a successful response from multiple template languages. For example, payloads{{7*'7'}}stayTwigBack in49, inJinja2Back in7777777. So don’t jump to conclusions just because you’ve responded successfully.

utilize

After detecting potential vulnerabilities and successfully identifying the template engine, you can start to try to find ways to exploit it. Please refer to the following for details.

How to prevent template injection vulnerability on server side

The best way to prevent users from submitting new templates or modifying them is to prevent them. However, this is sometimes inevitable due to business needs.

One of the easiest ways to avoid the introduction of server-side template injection vulnerability is to always use “illogical” template engine unless absolutely necessary, such asMustache. The separation of logic and representation can greatly reduce the risk of high-risk template based attacks.

Another measure is to execute the user’s code only in a sandbox environment where potentially dangerous modules and functions have been completely removed. Unfortunately, sandboxing untrusted code is inherently difficult and easy to bypass.

Finally, for the unavoidable situation of accepting arbitrary code execution, another supplementary method is to apply your own sandbox by deploying the template environment in a locked container such as docker.


Using server template injection vulnerability

In this section, we’ll take a closer look at some typical server-side template injection vulnerabilities and demonstrate how to take advantage of the previously summarized methods. By putting it into practice, you can potentially discover and exploit various server-side template injection vulnerabilities.

Once the server template injection vulnerability is found and the template engine in use is determined, the successful exploitation of the vulnerability usually involves the following process.

  • read

    • Template syntax
    • Security document
    • Known exploits
  • Explore the environment
  • Construct custom attack

read

Unless you already know the template engine well, you should read its documentation first. While this may be a bit boring, don’t underestimate that documentation can be a useful source of information.

Learn basic template grammar

Learning basic grammar, key functions and variable handling is obviously important. Even simply learning how to embed native code blocks in a template can sometimes lead to exploits quickly. For example, once you know you are using the Python based Mako template engine, implementing remote code execution can be as simple as:

<%
import os
x=os.popen('id').read()
%>
${x}

In a non sandbox environment, it is very simple to implement remote code execution and use it to read, edit or delete arbitrary files in many common template engines.

Read the safety section

In addition to providing the basics of how to create and use templates, the document may also provide some kind of “security” section. The name of this section will be different, but it usually outlines all the potentially dangerous things that people should avoid using templates. This can be a valuable resource, even as a memo, to guide you on what behaviors to look for and how to use them.

Even without a specific “security” section, if a particular built-in object or function poses a security risk, there is almost always a warning in the document. This warning may not provide much detail, but at least it should be marked as something that can be further explored.

For example, in the ERB template, the document display can list all the directories, and then read any file as follows:

<%= Dir.entries('/') %>
<%= File.open('/example/arbitrary-file').read %>

Find known exploits

Another key aspect of using server-side template injection vulnerability is to be good at finding other online resources. Once you can identify the template engine you are using, you should browse the web to find any vulnerabilities that others may have found. Due to the widespread use of some major template engines, well-documented exploits may sometimes be found, which you can adjust to take advantage of to your target website.

explore

At this point, you may have stumbled upon a viable exploit when using documents. If not, the next step is to explore the environment and try to discover all the objects you can access.

Many template engines expose certain types ofselforenvironmentObject, which acts like a namespace that contains all the objects, methods, and properties supported by the template engine. If such an object exists, it can potentially be used to generate a list of objects in scope. For example, in a Java based template language, you can sometimes use the following injection to list all variables in the environment:

${T(java.lang.System).getenv()}

This can be used as a basis for creating a short list of potentially interesting objects and methods for further study.

Objects provided by developers

It should be noted that the website will contain built-in objects provided by templates and custom, site-specific objects provided by web developers. You should pay special attention to these non-standard objects, because they may contain sensitive information or available methods. Since these objects may vary between different templates in the same website, please note that you may need to study the behavior of the object in the context of each different template before you can find a way to use it.

Although server-side template injection may lead to remote code execution and complete server takeover, it is not always possible in practice. However, just excluding remote code execution does not necessarily mean that there are no other types of attacks. You can still use the server-side template injection vulnerability for other high-risk attacks, such as directory traversal, to access sensitive data.

Construct custom attack

So far, we have focused on building attacks by reusing recorded vulnerabilities or using known vulnerabilities in the template engine. However, sometimes you need to build a custom exploit. For example, you may find that the template engine executes templates in a sandbox, which makes the attack difficult or even impossible.

After identifying the attack point, if there is no obvious way to exploit the vulnerability, you should continue to use traditional audit techniques to check the exploitable behavior of each function. By methodically completing this process, you can sometimes build a complex attack that can even be used against more secure targets.

Using object chain to construct custom attack

As mentioned above, the first step is to identify the objects and methods that you have access to. Some objects may jump out immediately. By combining your own knowledge with the information provided in the document, you should be able to put together a short list of objects that you want to mine more thoroughly.

When studying the documents of objects, pay special attention to which methods these objects are allowed to access and which objects they return. By delving into the document, you can find combinations of objects and methods that can be linked together. Linking the right objects and methods together sometimes allows you to access dangerous features and sensitive data that initially seem out of reach.

For example, in velocity, a Java based template engine, you can call$classvisitClassToolObject. Research documents show that you can use chaining$class.inspect()Methods and$class.typeProperty refers to any object. In the past, this was used to execute shell commands on the target system, as follows:

$class.inspect("java.lang.Runtime").type.getRuntime().exec("bad-stuff-here")

Using objects provided by developers to construct custom attacks

Some template engines run in a secure and locked environment by default, so as to reduce the related risks as much as possible. Although this makes it difficult to use these templates for remote code execution, the objects exposed to the templates created by developers can provide further attack points.

However, although a large number of documents are usually provided for template built-in objects, site-specific objects are almost not documented at all. Therefore, to know how to exploit these vulnerabilities, you need to manually investigate the behavior of the website to determine the attack point, and build your own custom attack accordingly.

Server side template injection of Web Security

Recommended Today

What is “hybrid cloud”?

In this paper, we define the concept of “hybrid cloud”, explain four different cloud deployment models of hybrid cloud, and deeply analyze the industrial trend of hybrid cloud through a series of data and charts. 01 introduction Hybrid cloud is a computing environment that integrates multiple platforms and data centers. Generally speaking, hybrid cloud is […]