在JavaScript中如何转义</script>标签?

9

我正在使用backbone框架,当页面加载时传递集合的一般方法是:

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

一切都很好,运行良好,直到有人决定在一个存储字段中添加文本"<script>alert("owned")</script>"。最后的</script>显然关闭了JavaScript。如何规避这个问题?

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

以上输出结果为:

<script>
    //<![CDATA[
      $(function() {
        window.router = new Dotz.Routers.ManageRouter({store: '{"_id":"4f3300e19c2ee41d9a00001c", "points_text":"<script>alert(\"hey\");</script>"'});
        Backbone.history.start();
      });
    //]]>
  </script>
3个回答

15

<script>块内,任何以</开头的标签都是语法不合法的,不仅仅是</script>需要转义,所以您需要在任何可能出现的地方进行转义。例如:

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

这将在JavaScript字符串中创建序列<\/,它被解释为与</相同。确保在您的gsub替换字符串中使用单引号,否则由于Ruby中单引号和双引号之间的差异,您可以使用gsub("</", "<\\/")

演示如下:

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>

如果你使用Rails(或ActiveSupport),你可以使用JSON转义

ActiveSupport::JSON::Encoding.escape_html_entities_in_json = true

实际应用中的效果:

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
#=> ["\u003Cb\u003Efoo\u003C/b\u003E"]

它生成的JSON比你解决这个特定问题所需的更加冗长,但它很有效。


4
魔术词是:
ActiveSupport.escape_html_entities_in_json = true

虽然已被标记为过时,但在当前的Rails版本中仍然有效(请参见我的rails c):

ruby-1.9.3-head :001 > ::Rails.version
 => "3.2.1" 
ruby-1.9.3-head :002 > ["<>"].to_json
 => "[\"<>\"]" 
ruby-1.9.3-head :003 > ActiveSupport.escape_html_entities_in_json = true
 => true 
ruby-1.9.3-head :004 > ["<>"].to_json
 => "[\"\\u003C\\u003E\"]" 

此表单已在Rails v2.3.3+中停用。 - Phrogz
可能是他们或者你使用了向后兼容的适配层。在原始的 ActiveSupport v3.0.7 中它无法正常工作,即便如此,我会取消对你所说它能工作的负评。 - Phrogz
这在我的Rails 3.2.13应用程序中非常有效。我想知道为什么ActiveSupport团队会弃用这样一个有用的、与安全相关的功能。 - sffc

-1
你忘记了''。
:javascript
    $(function() {
      window.router = new Dotz.Routers.ManageRouter({store: '#{@store.to_json}'});
      Backbone.history.start();
    });

不行。它仍然会呈现类似于{id: '324234', text: '</script>'...的内容,而这将关闭脚本。 - CamelCamelCamel
请问您能否发布渲染页面的HTML代码吗? - Blacksad

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接