记一次JAVA WEB项目解决XSS攻击的办法(亲测有效)

Posted on 2019-03-01 13:22  zkongbai  阅读(15595)  评论(4编辑  收藏  举报
  • 什么是XSS攻击

    简单来说,XSS 攻击是页面被注入了恶意的代码,度娘一大堆的东西,不想说

  • 系统架构主要是SSM框架,服务层另外使用了DubboX.

     为啥说这个,因为SpringMVC对于Xss攻击需要特殊处理

  • 思路  

    其实XSS工具解决思路就是捕获客户端提交的参数进行捕获,然后对参数值进行过滤处理,去除那些非法的字符.

    但是请求通常分为GET请求与POST请求,针对不同的请求,处理方式是不一样的

  • 步骤:

    1.针对GET与非文件格式上传的post请求.(form 表单提交的时候 没有这个参数enctype="multipart/form-data"),JSON请求等

1) web.xml配置过滤器

 1 <!-- xxs过滤 --> 
 2 <filter> 
 3     <filter-name>XssSqlFilter</filter-name> 
 4     <filter-class>cn.ffcs.web.filter.XssFilter</filter-class> 
 5 </filter> 
 6 <filter-mapping> 
 7     <filter-name>XssSqlFilter</filter-name> 
 8     <url-pattern>/*</url-pattern> 
 9     <dispatcher>REQUEST</dispatcher> 
10 </filter-mapping> 
View Code

2)过滤器实现 XssFilter.java,针对部分特殊请求,要求不走过滤的,可以在此过滤器中放行

 1 package cn.ffcs.web.filter;
 2 
 3 import java.io.IOException;
 4 
 5 import javax.servlet.FilterChain;
 6 import javax.servlet.ServletException;
 7 import javax.servlet.http.HttpServletRequest;
 8 import javax.servlet.http.HttpServletResponse;
 9 
10 import org.slf4j.Logger;
11 import org.slf4j.LoggerFactory;
12 import org.springframework.web.filter.OncePerRequestFilter;
13 
14 public class XssFilter extends OncePerRequestFilter {
15      private final Logger logger = LoggerFactory.getLogger(this.getClass());
16      @Override
17         protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
18                 throws ServletException, IOException {
19             try {
20                 String uri = request.getRequestURI();
21                 //特殊url不走过滤器
22                 if (uri.contains("receipt") || uri.contains("mobile/buildingMgr")
23                          || uri.contains("bestPay") || uri.contains("backNotify") || uri.contains("frontNotify")
24                          || uri.contains("queryOrder") || uri.contains("refundNotify") || uri.contains("refund")
25                          || uri.contains("reverse")) {
26                     chain.doFilter(request, response);
27                 } else {
28                     XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper((HttpServletRequest) request);
29                     chain.doFilter(xssRequest, response);
30                 }
31             } catch (Exception e) {
32                 logger.error("Xss过滤器,包装request对象失败");
33                 chain.doFilter(request, response);
34             }                
35         }
36 }
View Code

3) XssHttpServletRequestWrapper

  1 package cn.ffcs.web.filter;
  2 
  3 import javax.servlet.http.HttpServletRequest;
  4 import javax.servlet.http.HttpServletRequestWrapper;
  5 
  6 public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
  7 
  8     HttpServletRequest orgRequest = null;
  9      
 10     public XssHttpServletRequestWrapper(HttpServletRequest request) {
 11         super(request);
 12         orgRequest = request;
 13     }
 14  
 15     /**
 16      * 覆盖getParameter方法,将参数名和参数值都做xss过滤
 17      */
 18     @Override
 19     public String getParameter(String name) {
 20         String value = super.getParameter(xssEncode(name));
 21         if (value != null) {
 22             value = xssEncode(value);
 23         }
 24         return value;
 25     }
 26     /**
 27      * 覆盖getParameterValues方法,将参数名和参数值都做xss过滤
 28      */
 29     public String[] getParameterValues(String parameter) {
 30         String[] values = super.getParameterValues(parameter);
 31         if (values==null)  {
 32             return null;
 33         }
 34         int count = values.length;
 35         String[] encodedValues = new String[count];
 36         for (int i = 0; i < count; i++) {
 37             encodedValues[i] = xssEncode(values[i]);
 38         }
 39         return encodedValues;
 40     }
 41     
 42     /**
 43      * 获取request的属性时,做xss过滤
 44      */
 45      @Override
 46     public Object getAttribute(String name) {
 47         Object value = super.getAttribute(name);
 48         if (null != value && value instanceof String) {
 49             value = xssEncode((String) value);
 50         }
 51         return value;
 52     };
 53     
 54     /**
 55      * 覆盖getHeader方法,将参数名和参数值都做xss过滤。<br/>
 56      */
 57     @Override
 58     public String getHeader(String name) {
 59         String value = super.getHeader(xssEncode(name));
 60         if (value != null) {
 61             value = xssEncode(value);
 62         }
 63         return value;
 64     }
 65     
 66     
 67     /**
 68      * 将容易引起xss漏洞的半角字符直接替换成全角字符
 69      * 
 70      * @param s
 71      * @return
 72      */
 73     private static String xssEncode(String s) {
 74         return XssEncode.xssEncode(s);
 75     }
 76  
 77     /**
 78      * 获取最原始的request
 79      * 
 80      * @return
 81      */
 82     public HttpServletRequest getOrgRequest() {
 83         return orgRequest;
 84     }
 85  
 86     /**
 87      * 获取最原始的request的静态方法
 88      * 
 89      * @return
 90      */
 91     public static HttpServletRequest getOrgRequest(HttpServletRequest req) {
 92         if (req instanceof XssHttpServletRequestWrapper) {
 93             return ((XssHttpServletRequestWrapper) req).getOrgRequest();
 94         }
 95  
 96         return req;
 97     }
 98     
 99 
100 }
View Code

4) 使用到的编码工具,过滤参数使用了xss-html-filter工具,具体可以自行替换

 1 package cn.ffcs.web.filter;
 2 
 3 import net.sf.xsshtmlfilter.HTMLFilter;
 4 
 5 public class XssEncode {
 6     public static String xssEncode(String s) {
 7         if (s == null || s.isEmpty()) {
 8             return s;
 9         }
10         try {
11             HTMLFilter htmlFilter = new HTMLFilter();
12             String clean = htmlFilter.filter(s);
13             return clean;
14         } catch (NullPointerException e) {
15             return s;
16         } catch (Exception ex) {
17             ex.printStackTrace();
18         }
19  
20         return null;
21     }
22 }
View Code

5) pom.xml 配置引用的jar

1 <dependency>
2        <groupId>net.sf.xss-html-filter</groupId>
3        <artifactId>xss-html-filter</artifactId>
4        <version>1.5</version> 
5 </dependency>
View Code

    2.针对enctype="multipart/form-data"格式的post提交

1) 更改springMVC默认Annotation适配器(org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter - ->    cn.ffcs.web.filter.XssAnnotationMethodHandlerAdapter),如果没有则添加

1 <!-- annotation方法修饰器 -->
2 <bean id="handlerAdapter" class="cn.ffcs.web.filter.XssAnnotationMethodHandlerAdapter">
3 
4 ....
5 
6 <bean>

2) 继承AnnotationMethodHandlerAdapter 并覆盖handle方法

 1 package cn.ffcs.web.filter;
 2 
 3 import java.util.Map;
 4 import java.util.Set;
 5 
 6 import javax.servlet.http.HttpServletRequest;
 7 import javax.servlet.http.HttpServletResponse;
 8 
 9 import net.sf.xsshtmlfilter.HTMLFilter;
10 
11 import org.apache.commons.lang.StringUtils;
12 import org.springframework.web.servlet.ModelAndView;
13 import org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter;
14 @SuppressWarnings("deprecation")
15 public class XssAnnotationMethodHandlerAdapter extends
16         AnnotationMethodHandlerAdapter {
17     
18     
19     @SuppressWarnings({ "rawtypes", "unchecked" })
20     private void myXss(HttpServletRequest request){
21         Map map = request.getParameterMap();
22         Set<String> keySet = map.keySet();
23         for(String key : keySet){
24             String[] values = request.getParameterValues(key);
25             if(values!=null&&values.length>0){
26                 for(int i=0 ;i<values.length;i++){
27                     if(!StringUtils.isBlank(values[i])){
28                         values[i] = XssEncode.xssEncode(values[i]);
29                     }
30                 }
31             }
32         }
33     }
34     
35     @Override
36     public ModelAndView handle(HttpServletRequest request,
37             HttpServletResponse response, Object handler) throws Exception {
38         myXss(request);
39         return super.handle(request, response, handler);
40     }
41 }
View Code

 

tip: 网上另外有说用反射实现带@Controller的控制器,感觉思路可以,但是没有成功.