欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2022-03-28 19:15:14
springmvc filter防止xss注入跨站脚本工具(cross 斯特scripting),为不和层叠样式表(cascading style sheets,css)的缩写混淆,故将跨站脚本攻击缩...

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判断预防)。

@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处理。

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中

具体实现功能代码:

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 配置对象:

@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);
          }
}

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