2012-02-12 2 views
9

Я использую позвоночник, и общий путь для прохождения коллекции, когда нагрузка страницыСпасаясь</script> тег внутри Javascript

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> 

ответ

14

Внутри <script> блока это syntactically illegal иметь любой </ следует имя, а не только </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 escaping:

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 это более подробно, чем вам нужно решить эту конкретную проблему, но она эффективна.

-1

Вы забыли ''

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

Нету. он все равно отобразит что-то вроде '{id: '324234', текст: '' ...' пока закроет скрипт – CamelCamelCamel

+0

вы можете разместить HTML-страницу рендеринга, пожалуйста? – Blacksad

+0

обновил вопрос. – CamelCamelCamel

4

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

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

Эта форма была [снята с производства в Rails v2.3.3 +] (http://apidock.com/rails/ActiveSupport/escape_html_entities_in_json%3D/class) – Phrogz

+0

Работала над моей консолью 3.1.something rails. – iblue

+0

Нечетный; возможно, они или у вас есть обратная совместимость. Он не работает в сыром ActiveSupport v3.0.7; тем не менее я удалю свой нисходящий голос на вашем слове, что он работает. – Phrogz

Смежные вопросы