Экранирование тега внутри 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>
3 ответов
внутри <script>
блок синтаксически незаконным иметь какие-либо </
за ним следует имя-не просто </script>
-так что вам нужно бежать, что угодно может показаться. Например:
:javascript
var foo = { store: #{@store.to_json.gsub('</','<\/')} };
это создаст последовательность <\/
внутри ваших строк JS, которые интерпретируются так же, как </
. Убедитесь, что вы используете одинарные кавычки в строке замены gsub или используете 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, который является более подробным, чем вам нужно для решения этой конкретной проблемы, но он эффективен.
волшебное слово:
ActiveSupport.escape_html_entities_in_json = true
хотя он помечен как устаревший, он по-прежнему работает в текущих версиях rails (см. my 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\"]"
вы забыли "
:javascript
$(function() {
window.router = new Dotz.Routers.ManageRouter({store: '#{@store.to_json}'});
Backbone.history.start();
});