我正在Rails应用程序中呈现一个.js.erb
文件。在这个文件中,我正在更新一个选择框的选项。
最重要的是,我以一种XSS安全的方式进行操作。根据这个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
的显示文本被进行了HTML编码。例如,"Johnson & Johnson"的文本显示为:"Johnson &
Johnson"。其他特殊字符如撇号也会有相同的显示问题。尝试2
我知道Rails有一个html_safe
方法,所以我尝试使用它:我将"<%= blog.name %>";
更新为"<%= blog.name.html_safe %>";
。
blog.name
设置为alert("Gotcha");
来测试XSS时,它会出错:选项根本没有被更新。最终似乎问题是在这种上下文中使用html_safe
,应用程序不知道如何处理双引号。尝试3
这个方法似乎有效。它更新了选项,显示文本也正常工作,而显示文本为alert("gotcha");
的选项只是作为文本显示,而不会执行为代码:
// 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
模板中更新选择选项。
P粉5949413012024-03-31 11:24:38
尝试给出我的理解:
虽然你可以解码特殊字符,但这不是Rails的方式。
html_safe并不能确保字符串结果是安全的,而是你明确指定字符串是安全的,这样字符串中的HTML标签才能以HTML形式显示,因此它不能解决XSS问题。
string = '<div>html with string</div>' <%= string.html_safe %> # 以HTML形式显示 <%= string %> # 以字符串形式显示
根据这篇文章,在单引号或双引号中使用escape_javascript
是安全的。
# 安全 '<%= j string %>' # 或者 "<%= j string %>" # 不安全 <%= j string %> # 或者 `<%= j string %>`
因此,尝试3是XSS安全的,也是Rails的方式,是首选的。
你的代码可以简化为:
# html()方法会替换原始内容,所以你不需要先删除它 $('#blog_select_box') .html("<%= j options_from_collection_for_select(@blogs, :id, :name) %>");