我正在Rails應(yīng)用程式中呈現(xiàn)一個.js.erb
檔案。在這個文件中,我正在更新一個選擇框的選項。
最重要的是,我以一種XSS安全的方式進(jìn)行操作。根據(jù)這個Stack Overflow的解決方案,引用了OWASP DOM based XSS Prevention Cheat Sheet,我以以下方式更新選擇框的選項:
嘗試1
// app/views/blogs/blogs_select_listing.js.erb // 刪除所有選項 $('#blog_select_box').children().remove(); // 遍歷@blogs集合,將每個博客項目作為選項添加到選擇框中 <% @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時,它會出錯:選項根本沒有被更新。最終似乎問題是在這種上下文中使用html_safe
,應(yīng)用程式不知道如何處理雙引號。 嘗試3
#這個方法似乎有效。它更新了選項,顯示文字也正常運作,而顯示文字為alert("gotcha");
的選項只是作為文字顯示,而不會執(zhí)行為程式碼:
// app/views/blogs/blogs_select_listing.js.erb // 刪除所有選項 $('#blog_select_box').children().remove(); // 遍歷@blogs集合,將每個博客項目作為選項添加到選擇框中 $('#blog_select_box') .html("<%= j options_from_collection_for_select(@blogs, :id, :name) %>");
j
(escape_javascript
的別名)是不安全的。 目前還不清楚我如何以一種既安全又正確顯示文字的方式從.js.erb
範(fàn)本中更新選擇選項。
嘗試給出我的理解:
雖然你可以解碼特殊字元,但這不是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) %>");