Steal Restricted Sensitive Data with Template Languages

Template language is a language which allows developers defining placeholders that should later on be inserted or replaced with some dynamic data (variables). As it indicates from the definition, the main usage of template language is to give more flexibility to allow developers to insert some dynamic data into a predefined template. The dynamic data could be generated  from a different server or a new service based on the condition of existing sessions or use cases.  There are numerous templating languages widely used in web developments. Among them, Handlebars, EJS, Django, Mustache and Freemarker are very popular ones.  The three main components when using a  template language are , dynamic data(variables), template and the template engine to compile the data and template.

How Template Language works

As template languages provide more flexibility for web developments, it also introduces some security issues due to it. Clearly SSTI is the most notorious vulnerability discovered among various template languages.

Security Concerns beyond SSTI with Template Languages 

SSTI vulnerabilities could be avoid

Server Side Template Injections (SSTI) issues are the most common vulnerabilities discovered among many different languages. 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 on server-side when the template engine/processor processes the user supplied template. A list of vulnerable template languages and its exploitation injection code could be found here and it is quite comprehensive to understand.

Most of SSTI exploitation leads to arbitrary code execution and server compromise. Due to that, many template languages deploy default  Sandbox  and Sanitization features to prevent the template engine from accessing risky modules by disabling them in default settings. It means, when a user-provided template or data is processed by the engine, it can not access these risky modules even though the malicious template contains a call to the risky modules. For example,  HandleBars introduced a new restriction  to forbidden access prototype properties and methods of the context object by default since 4.6.0 to mitigate the code execution caused by server side template injections. Some applications using template language are also deploying a very strict sanitization method to disallow certain characters or regexes to prevent other vulnerabilities caused by SSTI, such as adding sanitize function against the final output to prevent XSS issues. 

Even though a strong Sandbox added by the template language itself and a robust sanitization method is deployed on the top of it to ensure the template could not be abused by SSTI attack ,  your applications could be still at risk due to improper configuration of how dynamic data could be consumed by the template engine.

Data leakage still occurs when template engines could process data out of the permitted scope.

Take the following instance as an example.


Under one application, an Admin user could create an organization and make sensitive operations through Dashboard or  performing API requests. Once an organization is created, the Admin could add multiple users with limited permission to the Organization settings. A user could invite new users to join the organization by sending them an invitation email. To make the email more dynamic and allow the users to modify the email template, it is using a template language to compile the email template.

Under a standard operation, a user could send an email to invite a new user by taking the following steps. 

Step 1:  A user could create the following email template from the dashboard and use it to send email to a new user.

<h2>Dear Friends </h2>
<div>  
<p>   Please join {{ organization.name }} to share your fun moments by clicking the invitation link {{organization.invitation_link}}. Your friends are waiting for you <p>
 <p>Best {{ user.name }}</p>
<div>

Step 2:  Application will process the email template with the template language engine once the user saves the template.

The application server will a) validate whether there are potential template injection threats by using both the sanitization and sandbox method  b)If the template is safe and syntax is correct, replace the placeholders like {{ organizatioin.name }}, {{ user. name }} with the dynamic data extracted from the server. For example, the App Server could query the DB and get the current Organization and user  data from DB and present it with a JSON object format.

Step 3:  The invitation email will be sent to another user with the final output.

Once the template engine replaces all the placeholders in the email template with the dynamic data to generate the final email output, an email will be sent to the invited user. 

Supposed that security control implemented on the server side is robust enough to prevent Server Side Template Injection attack by its sanitization and sandbox method,  But it could still leave an open security hole due to lack of access control of  dynamic data and insufficient validation when consuming the dynamic data.

Under this case, the organization data pulled from the application server contains more data than the user is permitted to access, for example, the api_key and api_private_token which should NOT be accessible by a team user  in a normal workflow. A non-admin user has no way to extract this sensitive data.

However, a user now could access them by crafting a deliberate template to steal them even without triggering any violations. If the user is using the following crafted template, the organization api_key and api_private_token will be disclosed to them when sending out an inviting email using this template.

<h2>Dear Friends </h2>
<div> 
 <p>   Please join {{ organization.name }} to share your fun moments by clicking the invitation link {{organization.invitation_link}}. Your friends are waiting for you.  <p>
 <p>Best {{ user.name }}</p> 
{{organization.api_key}} {{ogranization.api_private_token}}
<div>

Why does the template engine access more data than the users permitted?

There are various reasons why the server provides more data out of the user’s permission scope to the template engine when processing the template.  Here are three common reasons by referring to a couple of real scenarios that I experienced.

Reason 1:  Sanitization and sandbox method is only applied to check SSTI attacks patterns. 

If the user supplied template is NOT violating certain rules defined to match SSTI attack pattern, the server template engine will proceed the replacement action without validating whether the template is attempting to consume the data beyond its designed scope.

Reason 2:  Insufficient integration testing between micro services

It is very common for a company to have different teams for frontend and backend  service development. The Frontend team will be in charge of providing an interface for users to define a template and validate the user supplied template . Whereas,  the backend team will provide the functions to extract the dynamic data to replace the template once  the frontend passes a validated template to the backend. Both teams seem to perform their responsibility correctly, however, the frontend is blind to what kind of dynamic data the backend service provides and the backend has no way to validate which kind of data is allowed to be consumed by the frontend without a good suite of  integration tests.

Reason 3:  Access Control is not implemented in internal micro services

In a micro service development environment, I have seen many times that no access controls are deployed in the internal micro services. Once the request passes the access control implemented in the public services, the internal micro service is not going to perform another layer of validation when the public service calls the internal service. In this case, the internal service that pulls the organization data from the DB does not validate whether the user has the permission to access certain fields. 

How to prevent data leakage from abusing Template Language

To avoid data leakage caused by taking advantage of the template language, various means are available for developers to adopt during the development phase. 

  • Use a whitelist of dynamic data (variables in the template, {{ }}) rather than blacklist if a whitelist method is possible when validating the user supplied template
  • Perform the sanitization and validation after the user supplied template is compiled by the template engine to check whether there is potential sensitive data after the compilation..
  • Add access control and permission validation between services. If service A is going to consume data from service B, perform a permission check to ensure the user calling service A has the right permission to consume all the data provided by service B.

Besides adopting strict rules when processing template language during the development phase, a comprehensive and thorough test is vital to catch some overlooked areas.

Conclusion

While enjoying the flexibility provided by Template Language, developers and security teams should bear in mind that more flexibility also provides more attacking surface for malicious users. The SSTI issue is not the only security issue that you should be aware of,  you need to pay attention to the potential date leakage caused by insufficient sanitization or lack of access control to sensitive data. It means, your sanitization pattern should not only match potential SSTI attack patterns , but sensitive data patterns as well.

One thought on “Steal Restricted Sensitive Data with Template Languages

Leave a Reply

Your email address will not be published. Required fields are marked *