Discovering a Cross Site Scripting (XSS) vulnerability in Slim

What is Slim?

Slim is a templating engine for the Ruby ecosystem. It is a domain-specific language (DSL) that is meant to ease the burden of writing HTML views for Rubyists. Its lightweight syntax was inspired by Haml, another well known Ruby templating engine. Slim is very often used to create HTML views for Ruby on Rails & Sinatra websites. It is the most used templating engine after ERB (bundled with Rails) and Haml (its spiritual ancestor).

Here is simple Slim snippet:

This renders to:

Description of the vulnerability

At first glance; Slim syntax can seem simple. But it is, in fact, a very powerful tool, and offers many paths to achieve your templating goals. One such advanced feature offered by Slim is the ability to set attributes on HTML tags in a variety of ways (more on this in a moment). These are all described in depth in the project’s documentation.

On the one hand, creating HTML from a DSL is a deceptively simple task. One only has to write simple strings enclosed in brackets (<, >) and a full page can be created. On the other hand, the easy confusion of structure and content has caused many security issues over the years. These issues often end up referenced under the generic name: Cross Site Scripting (XSS). That is: an attacker could exploit this confusion to add new structure to the HTML page.

One such vulnerability was discovered earlier this year in Haml, and that we found is also present in Slim. In Haml, a developer can decide to have dynamic attributes on a tag created from a Ruby Hash. This is called using splat attributes. This same capability is also available in Slim.

If one does a template:

Where attrs is a ruby Hash containing: {id: “testId”, foo: “bar”}

Then the output will be:

The issue that was present earlier in Haml and that we discovered in Slim has to do with the content of this hash. Both Haml and Slim correctly escape the content of the attributes, but did not place any restriction on the name of the attributes. Hence if an attacker changes the content of our earlier example hash attrs to: {“><script>alert(1)</script><p id” => “testId”}

Slim will gladly render it to:

While this is not perfectly valid HTML, the script part will be executed by all known browsers.

Risk & Impact

The security risk here is quite big. It allows any attacker that can control a hash of attributes (often created by a form) to inject anything on the target website. This has been done any number of times to:

  • Inject advertising
  • Steal user & admin sessions to takeover their account
  • Redirect people to another lookalike website (often used to do targeted phishing).
  • Many more nefarious things

Fortunately setting attributes using the splat operator is not really often done. So most sites should already be safe.

Remediation

We discovered this vulnerability while creating new cross-site scripting protection rules for Sqreen. Sqreen will obviously protect apps against this kind of XSS and much more. Better that the vulnerability is fixed for everyone, however.

So, we contacted the Slim maintainers to inform them of the vulnerability. We also provided them with a fix (heavily inspired by the excellent work done by the Haml team). This was made available in a pull-request that is now merged.

The Slim gem itself has not yet been released (we will update the post as soon as it is done). So for site owners at the moment the best is either to:

  1. Look into your .slim files and check for splat attributes use. Change the affected files if you have dynamic attributes on a tag created from a Ruby Hash.
  2. Use the git version of slim by changing your Gemfile from:

to:

 

If you want to protect your Ruby on Rails app against more vulnerabilities, check out this article about Preventing SQL injections in Ruby. Or just install Sqreen to get your app automatically protected against cross-site scripting, SQL injections and more 😉