为什么要总结这一篇文章?防止大家少走一些弯路。Spring应用程序里面XSS防御,该怎么做?网上文章一大把,但是看起来感觉都有很大的问题。
至于什么是XSS在这里不解释了,常见的XSS攻击有三种:反射型XSS攻击、DOM-based型XSS攻击、存储型XSS攻击。我们在这里讲:反射型XSS攻击,DOM-based型怎么做。存储型XSS攻击一定要校验好上传文件的类型,不能只校验文件后缀名,使用文件头信息去校验。
在实际Web开发中,我们需要过滤或者编码页面传递给后台的特殊字符,防止XSS跨站脚本攻击。这个时候我们可以想到使用过滤器或者拦截器,至于为什么要选择Filter而不是Interceptor?我认为有两点:Filter依赖于Servlet容器,而Interceptor不依赖于Servlet容器;Filter对几乎所有的请求起作用,而Interceptor只能对action请求起作用。我先抛几个问题,希望可以引来不同的声音。
是否所有的请求都要去防御XSS?
比如一些比较复杂的富文本切带权限控制的没必要,我们可以通过配置文件设置一下白名单。建议使用绝对路径去控制,加上支持Ant风格-请求路径的一种匹配方式。
Header是否需要增加XSS防御?
需要比如通过头信息Referer去钓鱼欺骗,但是header的传递需要重新add,要不然下游是获取不到当前XssHttpServletRequestWrapper的头信息的。
代码语言:javascript复制 XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper((HttpServletRequest) request);
HttpServletRequest httpServletRequest = xssRequest.getOrgRequest();
Enumeration<?> er = httpServletRequest.getHeaderNames();
String headerName;
while (er.hasMoreElements()) {
headerName = er.nextElement().toString();
xssRequest.addHeader(headerName, httpServletRequest.getHeader(headerName));
}
chain.doFilter(xssRequest, response);
是否只需要重写基本方法?
@RequestParam是使用getParameterValues方法来获取参数值的,而不是getParameter方法。
所以只需要重写HttpServletRequestWrapper的getParameterValues方法,就可以解决上述无法覆盖的问题了。
getParameterNames,getParameterValues和getParameterMap等方法,也需要覆盖。同理,例如我们通过header中进行权限校验的时候,getHeaderNames方法也可能需要覆盖,不仅仅是覆盖getHeader方法,否则可能在某些特定场景下相关的参数值无法进入Filter,导致过滤缺失。
Controller里面使用Servlet,需要使用对应的ServletWrapper?
不需要,使用HttpServletRequest对象即可。request到达servlet之前拦截HttpServletRequest对象,也可以在服务方法转移控制后拦截HttpServletResponse对象。
责任链模式,通过httpServletRequest的装饰类HttpServletRequestWrapper来实现,只需要在装饰类中按照需要重写其对应的方法即可。
仅靠一个Filter能防御住XSS吗?
不能够完全能,需要运维和前后端一起配置,贴近实际业务那些是能过滤的,那些是不能过滤的。但是如果遇见混淆万能的XSS脚本咋办?好像没有什么好的解决方案。我们只要防御到大多数的攻击即可,尽量多加点缓解措施,提高利用成本,提高攻击门槛。
任何一个东西,不要总停留在网上现成的解决方案,勿在浮沙筑高台,实践是检验真理的唯一标准。
每周一句:人生没有太多的时间让自己原地打转及浪费,避开策略和目标的细节就是耍流氓。大家五一快乐!