2012-02-12 36 views
9

Tôi đang sử dụng xương sống, và cách tổng quát để thông qua các bộ sưu tập khi tải trang làThoát</script> thẻ bên javascript

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

đó là tốt và hoạt động tốt, cho đến khi ai đó quyết định thêm dòng chữ "<script>alert("owned")</script> "vào một trong các trường lưu trữ. cuối cùng </script> rõ ràng sẽ đóng javascript. Làm thế nào điều này có thể được phá vỡ?

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

Các kết quả trên:

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

Trả lời

14

Bên trong một khối <script> nó là syntactically illegal có bất kỳ </ theo sau là một tên không chỉ </script> —so bạn cần phải thoát ra bất cứ nơi nào nó có thể xuất hiện. Ví dụ:

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

Điều này sẽ tạo ra các chuỗi <\/ bên trong chuỗi JS của bạn, mà được hiểu là giống như </. Đảm bảo rằng bạn sử dụng dấu nháy đơn trong chuỗi thay thế gsub của bạn, hoặc sử dụng khác gsub("</", "<\\/") do sự khác biệt giữa dấu nháy đơn và dấu ngoặc kép trong Ruby.

Thể hiện trong hành động:

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> 

Nếu bạn đang sử dụng Rails (hoặc ActiveSupport) bạn có thể bật JSON escaping:

ActiveSupport::JSON::Encoding.escape_html_entities_in_json = true 

Seen trong hành động:

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

Nó tạo ra JSON đó là chi tiết hơn bạn cần giải quyết vấn đề cụ thể này, nhưng nó có hiệu quả.

-1

Bạn quên ''

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

nope. nó sẽ vẫn hiển thị một cái gì đó như '{id: '324234', văn bản: '' ...' trong khi sẽ đóng tập lệnh – CamelCamelCamel

+0

bạn có thể đăng HTML của trang được hiển thị không? – Blacksad

+0

đã cập nhật câu hỏi. – CamelCamelCamel

4

Từ ma thuật là:

ActiveSupport.escape_html_entities_in_json = true 

Mặc dù được đánh dấu là bị phản đối, điều này vẫn hoạt động trong các phiên bản ray hiện tại (xem tôi 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

Biểu mẫu này đã được [ngừng hoạt động trong Rails v2.3.3 +] (http://apidock.com/rails/ActiveSupport/escape_html_entities_in_json%3D/class) – Phrogz

+0

Nó hoạt động trên bảng điều khiển của tôi. – iblue

+0

Odd; có lẽ họ hoặc bạn có một shim tương thích ngược. Nó không hoạt động trong ActiveSupport raw v3.0.7; tuy nhiên tôi sẽ loại bỏ ý kiến ​​của tôi về từ của bạn mà nó hoạt động. – Phrogz

Các vấn đề liên quan