关于XSS漏洞修复

  XSS即恶意脚本攻击漏洞,详细的描述网上介绍的很详细。我说一下自己在工作中对这种漏洞的修复方案,仅供参考。

  第一阶段:使用ESAPI

  这是一个Apache开发的安全组件,主要用于解决SQL注入和恶意脚本注入。

  使用ESAPI防止XSS攻击时,首先应当配置过滤器(注意在过滤器中chain.doFilter(..)方法中的Request对象进行包装,在包装类中对请求参数进行筛选操作);其次将过滤器注册到web.xml文件中;最后配置Request的包装类,在其中对请求信息进行过滤。

 1 import java.io.IOException;
 2 import javax.servlet.Filter;
 3 import javax.servlet.FilterChain;
 4 import javax.servlet.FilterConfig;
 5 import javax.servlet.ServletException;
 6 import javax.servlet.ServletRequest;
 7 import javax.servlet.ServletResponse;
 8 import javax.servlet.http.HttpServletRequest;
 9 
10 /*
11  *配置XSS过滤器 
12  */
13 public class XSSFilter implements Filter {
14     @Override
15     public void init(FilterConfig filterConfig) throws ServletException {
16     }
17     @Override
18     public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
19         throws IOException, ServletException {
20         chain.doFilter(new XSSRequestWrapper((HttpServletRequest) request), response);
21     }
22     @Override
23     public void destroy() {
24     }
25 }
View Code
 1 <!-- XSS攻击防范 -->
 2 <filter>
 3     <filter-name>XSSFilter</filter-name>
 4     <filter-class>过滤器全类名</filter-class>
 5     </filter>
 6 <filter-mapping>
 7     <filter-name>XSSFilter</filter-name>
 8         <url-pattern>/*</url-pattern>
 9         <dispatcher>REQUEST</dispatcher>
10         <dispatcher>FORWARD</dispatcher>
11 </filter-mapping>
View Code
 1 import java.net.URLDecoder;
 2 import java.util.regex.Pattern;
 3 import javax.servlet.http.HttpServletRequest;
 4 import javax.servlet.http.HttpServletRequestWrapper;
 5 import org.owasp.esapi.ESAPI;
 6 
 7 /*
 8  * 对传入参数进行校验
 9  */
10 public class XSSRequestWrapper extends HttpServletRequestWrapper {
11     public XSSRequestWrapper(HttpServletRequest servletRequest) {
12         super(servletRequest);
13     }
14     @Override
15     public String[] getParameterValues(String parameter) {
16         String[] values = super.getParameterValues(parameter);        
17         if (values == null) {
18             return null;
19         }
20         int count = values.length;
21         String[] encodedValues = new String[count];
22         for (int i = 0; i < count; i++) {
23             encodedValues[i] = stripXSS(values[i]);
24         }
25         return encodedValues;
26     }
27     @Override
28     public String getParameter(String parameter) {
29         String value = super.getParameter(parameter);
30         return stripXSS(value);
31     }
32     @Override
33     public String getHeader(String name) {
34         String value = super.getHeader(name);
35         return stripXSS(value);
36     }
37 
38         private String stripXSS(String value) {
39         if (value != null) {
40             //解析URL编码,防止前台的编码后的参数进入ESAPI过滤后无法正常解码
41             value = URLDecoder.decode(value);
42              // 使用ESAPI的防护功能避免XSS攻击
43             value = ESAPI.encoder().canonicalize(value);
44             // 去除空字符
45             value = value.replaceAll("", "");
46             // 过滤脚本标签间(如:<script>..</script>)的内容
47             Pattern scriptPattern = Pattern.compile("<script>(.*?)</script>", Pattern.CASE_INSENSITIVE);
48             value = scriptPattern.matcher(value).replaceAll("");
49             //过滤由项目路径(src)直接访问项目资源的行为
50             scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\'(.*?)\\\'", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
51             value = scriptPattern.matcher(value).replaceAll("");
52             scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\"(.*?)\\\"", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
53             value = scriptPattern.matcher(value).replaceAll("");
54             // 过滤单个</script>标签
55             scriptPattern = Pattern.compile("</script>", Pattern.CASE_INSENSITIVE);
56             value = scriptPattern.matcher(value).replaceAll("");
57             // 过滤单个<script ...> 标签
58             scriptPattern = Pattern.compile("<script(.*?)>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
59             value = scriptPattern.matcher(value).replaceAll("");
60             // 过滤 eval(...) 表达式
61             scriptPattern = Pattern.compile("eval\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
62             value = scriptPattern.matcher(value).replaceAll("");
63             // 过滤e­xpression(...) 表达式
64             scriptPattern = Pattern.compile("e­xpression\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
65             value = scriptPattern.matcher(value).replaceAll("");
66             // 过滤javascript:表达式攻击
67             scriptPattern = Pattern.compile("javascript:", Pattern.CASE_INSENSITIVE);
68             value = scriptPattern.matcher(value).replaceAll("");
69             // 过滤vbscript:表达式攻击
70             scriptPattern = Pattern.compile("vbscript:", Pattern.CASE_INSENSITIVE);
71             value = scriptPattern.matcher(value).replaceAll("");
72             // 过滤onload=事件
73             scriptPattern = Pattern.compile("onload(.*?)=", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
74             value = scriptPattern.matcher(value).replaceAll("");
75         }
76         return value;
77     }
78 }
View Code

  注意:开启ESAPI的防护功能时(value = ESAPI.encoder().canonicalize(value);),需要提前对要筛选的值进行URL解码(value = URLDecoder.decode(value);),否则会出现中文乱码。

  第二阶段(可选):使用CSF(Content Security Policy)安全策略

  CSF是一种白名单防御策略,所有不在名单内的资源都不被信任,有效的防止了通过外部的标签、脚本、JS文件等资源的入侵形式,详情请看http://www.ruanyifeng.com/blog/2016/09/csp.html,我也是在这位大佬的网站上学习的CSF.

  使用方式:

  1.通过<meta http-equiv="Content-Security-Policy" content="script-src 'self'; object-src 'none'; style-src cdn.example.org third-party.org; child-src https:">标签将CSP嵌入到页面中。但是这种做法会对所有页面添加一个过滤项,加长了页面的访问时间,降低了用户体验;我加到项目中的时候还出现了某些样式文件加载不全的现象,没有必要不建议这么做。

  2.通过使用Nginx配置HTTP 头信息的Content-Security-Policy的字段,但是一般的公司都不允许更改Nginx,一旦Nginx做了某种配置,整个项目都受影响,这种方式基本没戏。

  

posted @ 2018-05-07 11:02  白先生的博客  阅读(7425)  评论(0编辑  收藏  举报