Meteor is an incredibly interesting framework from a security perspective. Due to the unique way in which it deals with it’s client/server separation, most of the information and functionality passed to the client is presented in a very uniform, organized way. From a black box security testing perspective, this can make life much easier!

We’ll start our black box adventure by searching for potential Cross Site Scripting (XSS) and/or Stored XSS attack vectors. One potential attack vector is the use of triple brace tags. Allowing un-sanitized user input into these raw tags can potentially let malicious users execute javascript on other clients’ machines. This is bad!

Finding Triple Braces

Thanks to the Spacebars compiler, we have all of the information we need to find templates that make use of triple braces.

Let’s take a tour of the template information given to each client. All of the templates used in the application live in the Template object. We can get a list of template names (along with some other Template specific object keys, such as instance, etc…) by grabbing the keys of the object:

Object.keys(Template);

If you’re interested in a particular template, you can drill into its renderFunction and access it directly, or turn it into a string and peruse the source:

Template.interestingTemplate.renderFunction.toString();

You’ll notice that the renderFunction holds the result of the Spacebars compilation process. The DOM is represented as HTMLjs objects, interspersed with Spacebars objects. In our case, the triple braces we’re looking for are transformed into calls to Spacebars.makeRaw.

Using this knowledge, we can easily find all of the templates that use triple braces throughout the application:

Object.keys(Template).filter(function(key){
    return Template[key] &&
           Template[key].renderFunction &&
           Template[key].renderFunction.toString().indexOf('Spacebars.makeRaw') > -1;
});

We could take this a step further by doing some monkey patching. Let’s replace the Spacebars.makeRaw method with a method that adds a data attribute to the first element passed into it:

Spacebars._makeRaw = Spacebars.makeRaw;
Spacebars.makeRaw = function (value) {
    function injectDataAttr() {
        var idx = value.indexOf('>');
        if (idx == -1) {
            return value;
        }
        return value.substr(0, idx) +
               ' data-make-raw' +
               value.substr(idx);
    }
    if (value == null)
        return null;
    else if (value instanceof HTML.Raw) {
        return HTML.Raw(injectDataAttr(value.value));
    }
    else {
        return HTML.Raw(injectDataAttr(value));
    }
};

You can then add a CSS rule to outline each raw element:

[data-make-raw] {
    outline: 1px solid tomato;
}

Or do it from the console:

var style = document.createElement("style");
style.appendChild(document.createTextNode(""));
document.head.appendChild(style);
style.sheet.insertRule('[data-make-raw] { outline: 1px solid tomato; }',0);

Here’s an example running against Telescope:

Telescope example

In this case I would make absolutely sure that the post title and each of the comments are being properly sanitized before being stored in the database and rendered on the client. If we miss either of these, we’re looking at a Stored XSS vulnerability!

What Does It All Mean?

This is just a tool to point you in the direction of potential vulnerabilities. It will show you all uses of triple braces throughout your application, but not all triple braces are bad! There are many valid uses of these raw tags, but you need to ensure that the content being rendered is truly safe. Always be sure to sanitize any user input that may find its way into a triple brace tag.

Also keep in mind that there are other XSS attack vectors such as the use of Spacebars.SafeString, dynamic attributes, and even within attribute values on certain attributes like href and onclick, to name a few.

Always be vigilant! Never trust user input!