Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
708 views
in Technique[技术] by (71.8m points)

ruby on rails - Escaping </script> tag inside javascript

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

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

1 Reply

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...