我正在Rails應(yīng)用程序中呈現(xiàn)一個.js.erb
文件。在這個文件中,我正在更新一個選擇框的選項(xiàng)。
最重要的是,我以一種XSS安全的方式進(jìn)行操作。根據(jù)這個Stack Overflow的解決方案,引用了OWASP DOM based XSS Prevention Cheat Sheet,我以以下方式更新選擇框的選項(xiàng):
嘗試1
// app/views/blogs/blogs_select_listing.js.erb // 刪除所有選項(xiàng) $('#blog_select_box').children().remove(); // 遍歷@blogs集合,將每個博客項(xiàng)目作為選項(xiàng)添加到選擇框中 <% @blogs.each do |blog| %> var opt = document.createElement("option"); opt.setAttribute("value", "<%= blog.id %>"); opt.textContent = "<%= blog.name %>"; $('#blog_select_box').append(opt); <% end %>
blog.name
的顯示文本被進(jìn)行了HTML編碼。例如,"Johnson & Johnson"的文本顯示為:"Johnson &
Johnson"。其他特殊字符如撇號也會有相同的顯示問題。嘗試2
我知道Rails有一個html_safe
方法,所以我嘗試使用它:我將"<%= blog.name %>";
更新為"<%= blog.name.html_safe %>";
。
blog.name
設(shè)置為alert("Gotcha");
來測試XSS時(shí),它會出錯:選項(xiàng)根本沒有被更新。最終似乎問題是在這種上下文中使用html_safe
,應(yīng)用程序不知道如何處理雙引號。嘗試3
這個方法似乎有效。它更新了選項(xiàng),顯示文本也正常工作,而顯示文本為alert("gotcha");
的選項(xiàng)只是作為文本顯示,而不會執(zhí)行為代碼:
// app/views/blogs/blogs_select_listing.js.erb // 刪除所有選項(xiàng) $('#blog_select_box').children().remove(); // 遍歷@blogs集合,將每個博客項(xiàng)目作為選項(xiàng)添加到選擇框中 $('#blog_select_box') .html("<%= j options_from_collection_for_select(@blogs, :id, :name) %>");
j
(escape_javascript
的別名)是不安全的。目前還不清楚我如何以一種既安全又正確顯示文本的方式從.js.erb
模板中更新選擇選項(xiàng)。
嘗試給出我的理解:
雖然你可以解碼特殊字符,但這不是Rails的方式。
html_safe并不能確保字符串結(jié)果是安全的,而是你明確指定字符串是安全的,這樣字符串中的HTML標(biāo)簽才能以HTML形式顯示,因此它不能解決XSS問題。
string = '<div>html with string</div>' <%= string.html_safe %> # 以HTML形式顯示 <%= string %> # 以字符串形式顯示
根據(jù)這篇文章,在單引號或雙引號中使用escape_javascript
是安全的。
# 安全 '<%= j string %>' # 或者 "<%= j string %>" # 不安全 <%= j string %> # 或者 `<%= j string %>`
因此,嘗試3是XSS安全的,也是Rails的方式,是首選的。
你的代碼可以簡化為:
# html()方法會替換原始內(nèi)容,所以你不需要先刪除它 $('#blog_select_box') .html("<%= j options_from_collection_for_select(@blogs, :id, :name) %>");