我正在努力防止基于Java,基于Spring的Web应用程序中的跨站点脚本(XSS)。我已经实现了一个类似于这个例子http://greatwebguy.com/programming/java/simple-cross-site-scripting-xss-servlet-filter/的servlet过滤器,它清理了应用程序的所有输入。作为额外的安全措施,我还想清理所有JSP中应用程序的所有输出。我做了一些研究,看看如何做到这一点,并找到了两个互补的选择。
其中一个是使用Spring的defaultHtmlEscape
属性。这很容易实现(web.xml中的几行),当你的输出通过spring的标签之一(即:消息或表单标签)时,它非常有用。我发现的另一个选择是不直接使用${...}
之类的EL表达式而是使用<c:out value="${...}" />
第二种方法完美无缺,但由于我正在处理的应用程序的大小(200多个JSP文件)。使用c:out
标记替换EL表达式的所有不当使用是一项非常麻烦的任务。此外,确保所有开发人员都遵守使用c:out
标记的惯例(更不用说,代码将无法读取多少),这将成为一项繁琐的任务。
是否有其他方法来转义需要较少代码修改的EL表达式输出?
答案 0 :(得分:11)
从Servlet 2.5 / JSP 2.1开始,您可以创建一个自定义ELResolver
。您可以在ServletContextListener#contextInitialized()
注册。
@Override
public void contextInitialized(ServletContextEvent event) {
JspFactory.getDefaultFactory()
.getJspApplicationContext(event.getServletContext())
.addELResolver(new YourCustomELResolver());
}
在ELResolver#getValue()
你可以做逃脱的工作。
你唯一的问题是,你将无法在允许的地方显示HTML(即已经通过白名单的恶意标签/属性进行了清理,这样你最终会得到像Jsoup can这样无辜的标签。
那就是说,我不同意在问题的第1段中提到的Filter
在输入期间逃避XSS的必要性。你冒着双重逃避的风险。你只需要在它可能受到伤害的那一点上逃脱它,即在视图一侧直接在HTML中输入内容,输出。我建议摆脱所谓的XSS过滤器,并通过使用JSTL <c:out>
或fn:escapeXml()
(或自定义EL解析器,集中你在视图侧修复它,但这绝对不是正常的方法)。未来的代码维护者将非常感激。
答案 1 :(得分:1)
This blog post描述了一个自定义ELResolver,它转义String类型的EL表达式值。注册此自定义ELResolver将导致它转义所有EL表达式的输出。在JSP必须以编程方式输出HTML的特殊情况下,您需要一种不涉及EL表达式的机制,例如自定义标记或scriptlet:
<%= "Java expression hopefully returning safe HTML" %>
答案 2 :(得分:1)
我同意你不应该在每个变量周围使用c:out。 我在http://tech.finn.no/2011/04/08/xss-protection-whos-responsibility/
写了一篇描述原因的博客这涉及很多内容。