服务器之家

服务器之家 > 正文

使用springMVC通过Filter实现防止xss注入

时间:2021-09-29 10:56     来源/作者:归田

springMVC Filter防止xss注入

跨站脚本工具(cross 斯特scripting),为不和层叠样式表(cascading style sheets,CSS)的缩写混淆,故将跨站脚本攻击缩写为XSS。

恶意攻击者往web页面里插入恶意scriptScript代码,当用户浏览该页之时,嵌入其中Web里面的Script代码会被执行,从而达到恶意攻击用户的目的。

防止XSS攻击简单的预防就是对Request请求中的一些参数去掉一些比较敏感的脚本命令。

原本是打算通过springMVC的HandlerInterceptor机制来实现的,通过获取request然后对request中的参数进行修改,结果虽然值修改了,但在Controller中获取的数值还是没有修改的。没办法就是要Filter来完成。

简单来说就是创建一个新的httpRequest类XsslHttpServletRequestWrapper,然后重写一些get方法(获取参数时对参数进行XSS判断预防)。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@WebFilter(filterName="xssMyfilter",urlPatterns="/*")
public class MyXssFilter implements Filter{
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {      
    }
 
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        XsslHttpServletRequestWrapper xssRequest = new XsslHttpServletRequestWrapper((HttpServletRequest)request);
        chain.doFilter(xssRequest , response);
    }
    
    @Override
    public void destroy() {    
    }  
}

XSS代码的过滤是在XsslHttpServletRequestWrapper中实现的,主要是覆盖实现了getParameter,getParameterValues,getHeader这几个方法,然后对获取的value值进行XSS处理。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
public class XsslHttpServletRequestWrapper extends HttpServletRequestWrapper {
  HttpServletRequest xssRequest = null
 public XsslHttpServletRequestWrapper(HttpServletRequest request) {
  super(request);
  xssRequest = request;
 }
 
  @Override
  public String getParameter(String name) { 
       String value = super.getParameter(replaceXSS(name)); 
         if (value != null) { 
             value = replaceXSS(value); 
         
         return value; 
  
  
  @Override
 public String[] getParameterValues(String name) {
   String[] values = super.getParameterValues(replaceXSS(name));
   if(values != null && values.length > 0){
    for(int i =0; i< values.length ;i++){
     values[i] = replaceXSS(values[i]);
    }
   }
  return values;
  }
  
  @Override
  public String getHeader(String name) { 
   
         String value = super.getHeader(replaceXSS(name)); 
         if (value != null) { 
             value = replaceXSS(value); 
         
         return value; 
     }
  /**
   * 去除待带script、src的语句,转义替换后的value值
   */
 public static String replaceXSS(String value) {
     if (value != null) {
         try{
          value = value.replace("+","%2B");   //'+' replace to '%2B'
          value = URLDecoder.decode(value, "utf-8");
         }catch(UnsupportedEncodingException e){
         }catch(IllegalArgumentException e){
     }
         
   // Avoid null characters
   value = value.replaceAll("\0", "");
 
   // Avoid anything between script tags
   Pattern scriptPattern = Pattern.compile("<script>(.*?)</script>", Pattern.CASE_INSENSITIVE);
   value = scriptPattern.matcher(value).replaceAll("");
 
   // Avoid anything in a src='...' type of e­xpression
   scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\'(.*?)\\\'", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
   value = scriptPattern.matcher(value).replaceAll("");
 
   scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\"(.*?)\\\"", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
   value = scriptPattern.matcher(value).replaceAll("");
 
   // Remove any lonesome </script> tag
   scriptPattern = Pattern.compile("</script>", Pattern.CASE_INSENSITIVE);
   value = scriptPattern.matcher(value).replaceAll("");
 
   // Remove any lonesome <script ...> tag
   scriptPattern = Pattern.compile("<script(.*?)>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
   value = scriptPattern.matcher(value).replaceAll("");
 
   // Avoid eval(...) e­xpressions
   scriptPattern = Pattern.compile("eval\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
   value = scriptPattern.matcher(value).replaceAll("");
 
   // Avoid e­xpression(...) e­xpressions
   scriptPattern = Pattern.compile("e­xpression\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
   value = scriptPattern.matcher(value).replaceAll("");
 
   // Avoid javascript:... e­xpressions
   scriptPattern = Pattern.compile("javascript:", Pattern.CASE_INSENSITIVE);
   value = scriptPattern.matcher(value).replaceAll("");
   // Avoid alert:... e­xpressions
   scriptPattern = Pattern.compile("alert", Pattern.CASE_INSENSITIVE);
   value = scriptPattern.matcher(value).replaceAll("");
   // Avoid οnlοad= e­xpressions
   scriptPattern = Pattern.compile("onload(.*?)=", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
   value = scriptPattern.matcher(value).replaceAll("");
   scriptPattern = Pattern.compile("vbscript[\r\n| | ]*:[\r\n| | ]*", Pattern.CASE_INSENSITIVE); 
   value = scriptPattern.matcher(value).replaceAll("");
  }        
     return filter(value);
 
  /**
   * 过滤特殊字符
   */
  public static String filter(String value) {
         if (value == null) {
             return null;
         }       
         StringBuffer result = new StringBuffer(value.length());
         for (int i=0; i<value.length(); ++i) {
             switch (value.charAt(i)) {
              case '<':
                  result.append("<");
                  break;
              case '>':
                  result.append(">");
                  break;
              case '"':
                  result.append(""");
                  break;
              case '\'':
                  result.append("'");
                  break;
              case '%':
                  result.append("%");
                  break;
              case ';':
                  result.append(";");
                  break;
           case '(':
                  result.append("(");
                  break;
              case ')':
                  result.append(")");
                  break;
              case '&':
                  result.append("&");
                  break;
              case '+':
                  result.append("+");
                  break;
              default:
                  result.append(value.charAt(i));
                  break;
          
         }
         return result.toString();
     }
}

SpringMVC 防止XSS 工具(常规方式)

要求:

xss过滤请求的参数:Content-Type为 json(application/json)

SpringMVC 对于application/json 转换处理说明:

spring mvc默认使用MappingJackson2HttpMessageConverter转换器,

而它是使用jackson来序列化对象的,如果我们能 将jackson的序列化和反序列化过程修改,加入过滤xss代码,并将其注册到MappingJackson2HttpMessageConverter中

具体实现功能代码:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import java.io.IOException;
import org.apache.commons.text.StringEscapeUtils;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
 
/**
 * 反序列化
 *
 */
public class XssDefaultJsonDeserializer extends StdDeserializer<String> {
 public XssDefaultJsonDeserializer(){
  this(null);
 }
 
 public XssDefaultJsonDeserializer(Class<String> vc) {
  super(vc);
 }
 
 @Override
 public String deserialize(JsonParser jsonParser, DeserializationContext ctxt) throws IOException, JsonProcessingException {
  // TODO Auto-generated method stub
  //return StringEscapeUtils.escapeEcmaScript(jsonParser.getText());
  return StringEscapeUtils.unescapeHtml4(jsonParser.getText());
 }
}

SpringMVC 配置对象:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Configuration
@EnableWebMvc
public class SpingMVCConfig extends WebMvcConfigurerAdapter {
 @Override
 public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
  super.configureMessageConverters(converters);
  // TODO Auto-generated method stub
  SimpleModule module = new SimpleModule();
  // 反序列化
  module.addDeserializer(String.class, new XssDefaultJsonDeserializer());
  // 序列化
  module.addSerializer(String.class, new XssDefaultJsonSerializer());
  ObjectMapper mapper = Jackson2ObjectMapperBuilder.json().build();
  // 注册自定义的序列化和反序列化器
  mapper.registerModule(module);
  MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(mapper);
  converters.add(converter);
          }
}

以上为个人经验,希望能给大家一个参考,也希望大家多多支持服务器之家。

原文链接:https://tianjunwei.blog.csdn.net/article/details/62053577

标签:

相关文章

热门资讯

yue是什么意思 网络流行语yue了是什么梗
yue是什么意思 网络流行语yue了是什么梗 2020-10-11
2020微信伤感网名听哭了 让对方看到心疼的伤感网名大全
2020微信伤感网名听哭了 让对方看到心疼的伤感网名大全 2019-12-26
背刺什么意思 网络词语背刺是什么梗
背刺什么意思 网络词语背刺是什么梗 2020-05-22
苹果12mini价格表官网报价 iPhone12mini全版本价格汇总
苹果12mini价格表官网报价 iPhone12mini全版本价格汇总 2020-11-13
2021年耽改剧名单 2021要播出的59部耽改剧列表
2021年耽改剧名单 2021要播出的59部耽改剧列表 2021-03-05
返回顶部