4 May 2013

Do not use RJS-like techniques

RJS (Ruby JavaScript) — a straightforward technique when server side (e.g. Rails app) responds with Javascript code and client-side eval-s it (Writing JS in Ruby is unrelated, I only consider response-evaling concept!)

Here are my usability and security concerns about this interaction.

Possibly other developers use their own RJS-like techniques — they can find my post helpful too.
(c) from http://slash7.com/assets/2006/10/8/RJS-Demistified_Amy-Hoy-slash7_1.pdf
  1. Broken concept & architecture. This feels as weird as the client-side sending code that is going to be evaled on the server-side... wait... Rails programmers had similar thing for a while :/
    Any RCEJS technique can be painlessly split into client's listeners and server's data.
  2. Escaping user content and putting it into Javascript can be more painful and having more pitfalls then normal HTML escaping. Even :javascript section used to be vulnerable in HAML (</script> breaks .to_json in Rails < 4). There can be more special characters and XSS you should care about.
  3. JSONP-like data leaking. If app accepts GET request and responds with Javascript containing private data in it attacker can use fake JS functions to leak data from the response. For example response is:

    Page.updateData("data")

    and attacker crafts such page:

    <script>var Page={updateData:function(leak){ ... }}</script>
    <script src="http://TARGET/get_data.js?params"></script>

    Voila, joys of RJS
  4. UPD as pointed out on HN evaling response will mess with your global namespace and there is no way to jump into closure you created request in..
Original RJS (Ruby-generates-JS) was removed by Yahuda Katz 6 years ago, he gave me this link with more details.

But I still see in the wild apps responding with private data in javascript. This is a very fragile technique, refactoring will both improve code quality and secureness of your app.

P.S. Cool, GH uses cutting edge HTML 5 security and added CSP headers. My thoughts:

  • Rails 4 has built-in default_headers (guess who added it?), which has better performance than before filter
  • current CSP is easily bypassed with JSONP trick, just write in console on github.com:
    document.write('<script src="https://github.com/rails.json?callback=alert(0)//"></script>')
    i will fix it when get spare time, btw: https://github.com/rails/rails/pull/9075
  • CSP is very far from ultimate XSS prevention. Really very far, especially for Rails's agileness and jquery_ujs. Github should consider privileged subdomains https://github.com/populr/subdomainbox