Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

I'm using backbone, and the general way for passing the collections when the page load is

window.router = new Routers.ManageRouter({store: #{@store.to_json});

which is fine and works well, until someone decides to add the text "<script>alert("owned")</script>" to one of the store fields. the last </script> obviously closes the javascript. How can this be circumvented?

  :javascript
    $(function() {
      window.router = new Dotz.Routers.ManageRouter({store: #{@store.to_json}});
      Backbone.history.start();
    });

The above outputs:

<script>
    //<![CDATA[
      $(function() {
        window.router = new Dotz.Routers.ManageRouter({store: '{"_id":"4f3300e19c2ee41d9a00001c", "points_text":"<script>alert("hey");</script>"'});
        Backbone.history.start();
      });
    //]]>
  </script>
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
668 views
Welcome To Ask or Share your Answers For Others

1 Answer

Inside a <script> block it is syntactically illegal to have any </ followed by a name—not just </script>—so you need to escape that anywhere it may appear. For example:

:javascript
   var foo = { store: #{@store.to_json.gsub('</','</')} };

This will create the sequence </ inside your JS strings, which is interpreted to be the same as </. Ensure that you use single quotes in your gsub replacement string, or else use gsub( "</", "<\/" ) due to the difference between single and double quotes in Ruby.

Shown in action:

irb:02.0> s = "<b>foo</b>" # Here's a dangerous string
#=> "<b>foo</b>"

irb:03.0> a = [s]          # Wrapped in an array, for fun.
#=> ["<b>foo</b>"]

irb:04.0> json = a.to_json.gsub( '</', '</' )  # Sanitized
irb:05.0> puts json        # This is what would come out in your HTML; safe!
#=> ["<b>foo</b>"]

irb:06.0> puts JSON.parse(json).first  # Same as the original? Yes! Yay!
#=> <b>foo</b>

If you are using Rails (or ActiveSupport) you can enable JSON escaping:

ActiveSupport::JSON::Encoding.escape_html_entities_in_json = true

Seen in action:

irb:02.0> a = ["<b>foo</b>"]
irb:03.0> puts a.to_json # Without the magic
#=> ["<b>foo</b>"]

irb:04.0> require 'active_support'
irb:05.0> ActiveSupport::JSON::Encoding.escape_html_entities_in_json = true
irb:06.0> puts a.to_json # With the magic
#=> ["u003Cbu003Efoou003C/bu003E"]

It produces JSON that is more verbose than you need to solve this particular problem, but it is effective.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...