Экранирование тега </script> внутри javascript - PullRequest
9 голосов
/ 12 февраля 2012

Я использую магистраль и общий способ передачи коллекций, когда загрузка страницы составляет

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 голосов
/ 12 февраля 2012

Внутри блока <script> синтаксически синтаксически *1003* запрещено иметь любое </, за которым следует имя, а не просто </script>, так что вам нужно избегать этого, где бы оно ни появлялось.Например:

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

Это создаст последовательность <\/ внутри ваших строк JS, которая интерпретируется как </.Убедитесь, что вы используете одинарные кавычки в строке замены gsub или же используете gsub( "</", "<\\/" ) из-за разницы между одинарными и двойными кавычками в Ruby.

Показано в действии:

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 голосов
/ 12 февраля 2012

Волшебное слово:

ActiveSupport.escape_html_entities_in_json = true

Хотя помечено как устаревшее, это все еще работает в текущих версиях рельсов (см. Мой 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\"]" 
0 голосов
/ 12 февраля 2012

Вы забыли ''

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