2012-02-12 2 views
9

sto usando spina dorsale, e il modo generale per far passare le collezioni in cui il caricamento della pagina èEscaping</script> tag all'interno javascript

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

che va bene e funziona bene, fino a quando qualcuno decide di aggiungere il testo "<script>alert("owned")</script> "a uno dei campi del negozio. l'ultimo </script> chiude ovviamente il javascript. Come può essere aggirato?

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

Le uscite di cui sopra:

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

risposta

14

all'interno di un blocco <script> è syntactically illegal avere alcun </ seguito da un nome, non solo </script> -che è necessario evitarlo ovunque possa apparire. Per esempio:

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

Questo creerà la sequenza <\/ dentro le corde JS, che è interpretato per essere lo stesso </. Assicurati di utilizzare virgolette singole nella stringa di sostituzione di gsub, oppure usa gsub("</", "<\\/") a causa della differenza tra virgolette singole e doppie in Ruby.

Indicato in azione:

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> 

Se si utilizza Rails (o ActiveSupport) è possibile attivare JSON escaping:

ActiveSupport::JSON::Encoding.escape_html_entities_in_json = true 

visto in azione:

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"] 

Produce JSON è più verboso di quanto tu abbia bisogno di risolvere questo particolare problema, ma è efficace.

-1

hai dimenticato il ''

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

no. renderà ancora qualcosa come '{id: '324234', testo: '' ...' mentre chiuderà lo script – CamelCamelCamel

+0

puoi pubblicare l'HTML della pagina visualizzata per favore? – Blacksad

+0

ha aggiornato la domanda. – CamelCamelCamel

4

La parola magica è:

ActiveSupport.escape_html_entities_in_json = true 

Anche se marcato come deprecato, questo funziona ancora nelle versioni rotaie correnti (vedi il mio 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

Questo modulo è stato [fuori produzione in Rails v2.3.3 +] (http://apidock.com/rails/ActiveSupport/escape_html_entities_in_json%3D/class) – Phrogz

+0

Ha funzionato sulla mia console di console 3.1.qualcosa. – iblue

+0

Dispari; forse loro o tu hai uno shim di compatibilità all'indietro. Non funziona in ActiveSupport v3.0.7 non elaborato; tuttavia rimuoverò il mio downvote sulla tua parola che funziona. – Phrogz