Exploitation of Server-Side Template Injection
Recap
Hey there, welcome back! Let’s do a quick recap of our previous article. We explored basics of server-side template injection (SSTI), understanding how attackers manipulate template engines to execute arbitrary code. We demonstrated this with a practical lab, showcasing the risks of SSTI attacks. We also highlighted preventive measures to mitigate the vulnerabilities.
In this article, we will delve into the fundamentals of crafting SSTI attacks and explore the available tools for executing these exploits.
Constructing Server-Side Template Injection Attacks
Detecting and exploiting these vulnerabilities requires a methodical approach. Let’s explore this approach further below:
Out of the three key phases, we will only focus on exploring two essential steps: detection and identification. The exploitation phase involves a more in-depth exploration, which we will delve into in future articles.
Step 1 - Detection
Detecting SSTI vulnerabilities begins by identifying areas within a web application where user input is directly inserted into templates.
One approach is to fuzz the template with polyglots comprised of special characters ${{<%[%'"}}%.
that is commonly used in template expressions. If the server raises an exception upon interpreting these characters, it indicates a potential SSTI vulnerability.
Nevertheless, regardless of the fuzzing outcomes, it’s crucial to undergo the following context-specific methods:
1. Plaintext context
In plaintext context, user input is directly embedded into the template without being encoded. This means that any special characters or code included in the input will be rendered directly on the page.
To detect plaintext context vulnerabilities, look for input fields or parameters where data provided by users is reflected in the output page without any enconding or sanitisation.
Example:
Consider a web application using the Jinja2 template engine.
from jinja2 import Template
template = Template("Hello, " + firstname)
output = template.render()
If the user injects {{7*7}}
as payload, the output will be Hello, 49
, which indicates a plaintext context vulnerability.
2. Code context
In code context, user input is inserted into the template code itself without properly sanitised or validated, leading to the execution of arbitrary code. This often occurs in template engines where expressions are evaluated within the template.
To detect code context vulnerabilities, look for template expressions that directly incorporate input from users without proper sanitisation.
Example:
Consider a web application using the Jinja2 template engine.
from jinja2 import Template
template = Template("Hello, {{ user.firstname }}")
output = template.render()
If the user injects the }}{{7*7}}
as payload, the output will be Hello, Peter49
, which indicates a code context vulnerability.
Step 2 - Identification
After detecting the potential for template injection, the subsequent task involves identifying the template engine in use. While there are numerous templating languages exist, many of them employ similar syntax to avoid conflicts with HTML characters.
In some cases, servers may disclose the template engine being used by displaying errors. Here are some invalid expressions that could potentially trigger errors:
For instance, <%= foobar %>
triggers the following error from the Ruby-based ERB engine.
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, we need to manually test and analyse how the template engine interpret it. This often involves injecting mathematical expressions using syntax specific to different template engines. We can use the decision tree similar like below to help with the process:
It’s important to note that a single payload may return a successful response in more than one template language. For instance, while {{7*'7'}}
payload results in 49
in Twig, it produces 7777777
in Jinja2. Therefore, it’s crucial to avoid drawing conclusions solely based on single successful response.
The diagram has been outdated since James released this research. For more insights on various template engines, you may refer here.
Server-Side Template Injection Detection Tools
There are several tools available for detecting and identifying SSTI vulnerabilities. Let’s explore some of these tools and their capabilities.
1. TInjA
Reference: TInjA.
Key features:
- A CLI tool known for its automatic detection of injection possibilities and comprehensive vulnerability assessment.
- Supports 44 template engines across eight languages, efficiently detecting both SSTI and CSTI vulnerabilities.
- Uses polyglots to ensure quick scans and broad applicability.
- Offers flexible usage options for seamless integration into security testing workflows.
2. Tplmap
Reference: Tplmap
Key features:
- A versatile tool for exploiting code injection and SSTI vulnerabilities.
- Offers sandbox escape techniques for accessing the underlying operating system.
- Supports various code contexts and blind njection scenarios, adapting to different attacks.
- Enables cross-language eval()-like code injections in multiple languages.
3. SSTImap
Reference: SSTImap
Key features:
- An evolution of Tplmap, known for its comprehensive detection capabilities.
- Excels in identifying both code injection and SSTI injection vulnerabilities.
- Supports eval()-like code injections and generic unsandboxed template engines.
4. Template Injection Table
Reference: Template Injection Table
Key features:
- Offers a vital resource for testing applications for template injection vulnerabilities.
- Provides a diverse collection of polyglots tailored for 44 key template engines.
- Offers efficient detection and identification capabilities.
- Facilitates vulnerability assessments, allowing for comprehensive testing.
Exploring Code Context Vulnerabilities
Let’s illustrate the server-side template injection (SSTI) vulnerabilities within code context through a practical lab from PortSwigger Academy.
Resource: PortSwigger: SSTI - Code Context
Scenario:
Exploitation of SSTI code context vulnerability in Tornado template for file deletion
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
Before we proceed, it’s essential to note that we will highlight the following SSTI methodology to assist us in tackling this lab.
-
Detect
Searching reflections of user-controlled input throughout the application. -
Identify
Enumerating the template engine by injecting payloads or triggering error conditions.
Step 1: Detect
Upon accessing the lab, we encountered a homepage displaying various blog posts.
Click on “View post” and notice the comment section where we can post comments.
Firstly, we need to log in to “My account” using the provided credentials.
Once logged in, we notice the presence of a feature called “Preferred name”. Let’s see how it works.
By utilising the Burp Suite, we can observe the request upon changing the preferred name.
In the context of the preferred name feature, note that the user’s preferred name is set within the coding context. This means that the application retrieves and uses the preferred name specified by the user for various interactions within the application.
blog-post-author-display=user.name
To conduct further analysis, we send the request containing the preferred name to the Burp Suite Repeater.
Back to the comment section, we post a comment containing general expression payloads for SSTI.
Refresh the page and observe that none of the expressions are evaluated but only user’s name is reflected back.
This indicates that the parameter blog-post-author-display=user.name
is the target for potential SSTI exploitation.
Step 2: Identify
Next, to identify which template engine is being used, we attempt to manipulate the user.name
parameter by append it with an invalid expression {{foobar}}
.
Request: blog-post-author-display=user.name}}{{foobar}}
After refreshing the page, we get the error message, which highlights that the Tornado templating engine is being used.
Thus, it is important to refer to the Tornado documentation or HackTricks SSTI - Tornado to understand the syntax used.
Step 3: Exploit
In Tornado template engine, the syntax employed is as follows:
{{ expression }}
Let’s inject the target point with {{7*7}}
. It’s important to append }}
before our payload to escape the user.name context. Since {{user.name}}
is already enclosed within double curly braces, we don’t need to include }}
in our payload.
Request: blog-post-author-display=user.name}}{{7*7
We observe that it evaluates the {{7*7}}
and outputs the result as 49
. Therefore, it indicates the presence of SSTI vulnerability.
Next, we must determine how to execute arbitrary code within the Tornado template. We can import Python modules to execute operating system commands.
Now, we can craft the payload to determine the current directory we are in.
Request: blog-post-author-display=user.name}}{% import os %}os.system('pwd')}
Currently, we are in Carlos’s home directory.
Then, we list the files in the directory to verify the existence of the target file morale.txt
.
Request: blog-post-author-display=user.name}}{% import os %}{os.system('ls')}
Indeed, the morale.txt
file is found in Carlos’s home directory.
In the final step, we successfully resolved the lab by deleting the morale.txt
file.
Request: blog-post-author-display=user.name}}{% import os %}{os.system('rm+morale.txt')}
That concludes the second article in this series. We hope you have gained valuable insights from this post. Stay tuned for the next articles.
References: