Java Filter过滤xss注入非法参数的方法

Posted 求知若渴 虚心若愚

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java Filter过滤xss注入非法参数的方法相关的知识,希望对你有一定的参考价值。

http://blog.csdn.NET/feng_an_qi/article/details/45666813

Java Filter过滤xss注入非法参数的方法

 

 

web.xml:

[html] view plain copy
 
  1. <filter>  
  2.        <filter-name>XSSFiler</filter-name>  
  3.        <filter-class>  
  4.            com.paic.mall.web.filter.XssSecurityFilter  
  5.        </filter-class>  
  6.     </filter>  
  7.     <filter-mapping>  
  8.         <filter-name>XSSFiler</filter-name>  
  9.         <url-pattern>*.jsp</url-pattern>  
  10.     </filter-mapping>  
  11.     <filter-mapping>  
  12.         <filter-name>XSSFiler</filter-name>  
  13.         <url-pattern>*.do</url-pattern>  
  14.     </filter-mapping>  
  15.     <filter-mapping>  
  16.         <filter-name>XSSFiler</filter-name>  
  17.         <url-pattern>*.screen</url-pattern>  
  18.     </filter-mapping>  
  19.     <filter-mapping>  
  20.         <filter-name>XSSFiler</filter-name>  
  21.         <url-pattern>*.shtml</url-pattern>  
  22.     </filter-mapping>  
  23.     <filter-mapping>  
  24.         <filter-name>XSSFiler</filter-name>  
  25.         <servlet-name>dispatcher</servlet-name>  
  26.     </filter-mapping>  

 

XssSecurityFilter.Java

[java] view plain copy
 
  1. public class XssSecurityFilter implements Filter {  
  2.   
  3.     protected final Logger log = Logger.getLogger(this.getClass());  
  4.   
  5.     public void init(FilterConfig config) throws ServletException {  
  6.         if(log.isInfoEnabled()){  
  7.             log.info("XSSSecurityFilter Initializing ");  
  8.         }  
  9.     }  
  10.   
  11.     /** 
  12.      * 销毁操作 
  13.      */  
  14.     public void destroy() {  
  15.         if(log.isInfoEnabled()){  
  16.             log.info("XSSSecurityFilter destroy() end");  
  17.         }  
  18.     }  
  19.   
  20.     public void doFilter(ServletRequest request, ServletResponse response,  
  21.             FilterChain chain) throws IOException, ServletException {  
  22.         HttpServletRequest httpRequest = (HttpServletRequest)request;  
  23.           
  24.         XssHttpRequestWrapper xssRequest = new XssHttpRequestWrapper(httpRequest);  
  25.         httpRequest = XssSecurityManager.wrapRequest(xssRequest);  
  26.         chain.doFilter(xssRequest, response);  
  27.     }  
  28.   
  29. }  

 

XssHttpRequestWrapper.Java

[java] view plain copy
 
  1. /** 
  2.  * @author  
  3.  * @date 
  4.  * @describe 主要是对参数进行xss过滤,替换原始的request的getParameter相关功能 
  5.  *      线程不安全 
  6.  *  
  7.  */  
  8. public class XssHttpRequestWrapper extends HttpServletRequestWrapper {  
  9.   
  10.     protected Map parameters;  
  11.   
  12.   
  13.       
  14.       
  15.     /** 
  16.      * 封装http请求 
  17.      *  
  18.      * @param request 
  19.      */  
  20.     public XssHttpRequestWrapper(HttpServletRequest request) {  
  21.         super(request);  
  22.     }  
  23.       
  24.       
  25.     @Override  
  26.     public void setCharacterEncoding(String enc)  
  27.             throws UnsupportedEncodingException {  
  28.         super.setCharacterEncoding(enc);  
  29.         //当编码重新设置时,重新加载重新过滤缓存。  
  30.         refiltParams();  
  31.     }  
  32.       
  33.     void refiltParams(){  
  34.         parameters=null;  
  35.     }  
  36.   
  37.     @Override  
  38.     public String getParameter(String string) {  
  39.         String strList[] = getParameterValues(string);  
  40.         if (strList != null && strList.length > 0)  
  41.             return strList[0];  
  42.         else  
  43.             return null;  
  44.     }  
  45.   
  46.     @Override  
  47.     public String[] getParameterValues(String string) {  
  48.         if (parameters == null) {  
  49.             paramXssFilter();  
  50.         }  
  51.         return (String[]) parameters.get(string);  
  52.     }  
  53.   
  54.     @Override  
  55.     public Map getParameterMap() {  
  56.         if (parameters == null) {  
  57.             paramXssFilter();  
  58.         }  
  59.         return parameters;  
  60.     }  
  61.   
  62.     /** 
  63.      *  
  64.      * 校验参数,若含xss漏洞的字符,进行替换 
  65.      */  
  66.     private void paramXssFilter() {  
  67.         parameters = getRequest().getParameterMap();  
  68.         XssSecurityManager.filtRequestParams(parameters, this.getServletPath());  
  69.     }  
  70.   
  71. }  

 

XssSecurityManager.java

[java] view plain copy
 
    1. /** 
    2.  * @author  
    3.  * @date 
    4.  * @describe 安全过滤配置管理类,统一替换可能造成XSS漏洞的字符为中文字符 
    5.  */  
    6. public class XssSecurityManager {  
    7.   
    8.     private static Logger log = Logger.getLogger(XssSecurityManager.class);  
    9.   
    10.     // 危险的javascript:关键字j av a script  
    11.     private final static Pattern[] DANGEROUS_TOKENS = new Pattern[] { Pattern  
    12.             .compile("^j\\s*a\\s*v\\s*a\\s*s\\s*c\\s*r\\s*i\\s*p\\s*t\\s*:",  
    13.                     Pattern.CASE_INSENSITIVE) };  
    14.   
    15.     // javascript:替换字符串(全角中文字符)  
    16.     private final static String[] DANGEROUS_TOKEN_REPLACEMENTS = new String[] { "JAVASCRIPT:" };  
    17.   
    18.     // 非法的字符集  
    19.     private static final char[] INVALID_CHARS = new char[] { ‘<‘, ‘>‘, ‘\‘‘,  
    20.             ‘\"‘, ‘\\‘ };  
    21.   
    22.     // 统一替换可能造成XSS漏洞的字符为全角中文字符  
    23.     private static final char[] VALID_CHARS = new char[] { ‘<‘, ‘>‘, ‘’‘, ‘“‘,  
    24.             ‘\‘ };  
    25.   
    26.     // 开启xss过滤功能开关  
    27.     public static boolean enable=false;  
    28.   
    29.     // url-patternMap(符合条件的url-param进行xss过滤)<String ArrayList>  
    30.     public static Map urlPatternMap = new HashMap();  
    31.       
    32.     private static HashSet excludeUris=new HashSet();  
    33.   
    34.     private XssSecurityManager() {  
    35.         // 不可被实例化  
    36.     }  
    37.     static {  
    38.         init();  
    39.     }  
    40.   
    41.     private static void init() {  
    42.         try {  
    43.             String xssConfig = "/xss_security_config.xml";  
    44.             if(log.isDebugEnabled()){  
    45.                 log.debug("XSS config file["+xssConfig+"] init...");  
    46.             }  
    47.             InputStream is = XssSecurityManager.class  
    48.                     .getResourceAsStream(xssConfig);  
    49.             if (is == null) {  
    50.                 log.warn("XSS config file["+xssConfig+"] not found.");  
    51.             }else{  
    52.                 // 初始化过滤配置文件  
    53.                 initConfig(is);  
    54.                 log.info("XSS config file["+xssConfig+"] init completed.");  
    55.             }  
    56.         }  
    57.         catch (Exception e) {  
    58.               
    59.             log.error("XSS config file init fail:"+e.getMessage(), e);  
    60.         }  
    61.           
    62.     }  
    63.   
    64.     private static void initConfig(InputStream is) throws Exception{  
    65.         DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();  
    66.   
    67.         DocumentBuilder builder=factory.newDocumentBuilder();  
    68.   
    69.         Element root = builder.parse(is).getDocumentElement();  
    70.         //-------------------  
    71.         NodeList nl=root.getElementsByTagName("enable");  
    72.         Node n=null;  
    73.         if(nl!=null && nl.getLength()>0){  
    74.             n=((org.w3c.dom.Element)nl.item(0)).getFirstChild();  
    75.         }  
    76.         if(n!=null){  
    77.             enable = new Boolean(n.getNodeValue().trim()).booleanValue();  
    78.         }  
    79.         log.info("XSS switch="+enable);  
    80.         //-------------------------  
    81.         nl=root.getElementsByTagName("filter-mapping");  
    82.         NodeList urlPatternNodes=null;  
    83.         if(nl!=null && nl.getLength()>0){  
    84.             Element  el=(Element)nl.item(0);  
    85.             urlPatternNodes=el.getElementsByTagName("url-pattern");  
    86.             //-----------------------------------------------------  
    87.             NodeList nl2=el.getElementsByTagName("exclude-url");  
    88.             if(nl2!=null && nl2.getLength()>0){  
    89.                 for(int i=0;i<nl2.getLength();i++){  
    90.                     Element e=(Element)urlPatternNodes.item(i);  
    91.                     Node paramNode=e.getFirstChild();  
    92.                     if(paramNode!=null){  
    93.                         String paramName=paramNode.getNodeValue().trim();  
    94.                         if(paramName.length()>0){  
    95.                             excludeUris.add(paramName.toLowerCase());  
    96.                         }  
    97.                     }  
    98.                 }  
    99.             }  
    100.         }  
    101.         //----------------------  
    102.         if(urlPatternNodes!=null && urlPatternNodes.getLength()>0){  
    103.             for(int i=0;i<urlPatternNodes.getLength();i++){  
    104.                 Element e=(Element)urlPatternNodes.item(i);  
    105.                 String urlPattern=e.getAttribute("value");  
    106.                 if(urlPattern!=null && (urlPattern=urlPattern.trim()).length()>0){  
    107.                     List filtParamList = new ArrayList(2);  
    108.                     if(log.isDebugEnabled()){  
    109.                         log.debug("Xss filter mapping:"+urlPattern);  
    110.                     }  
    111.                     //-------------------------------  
    112.                     NodeList temp=e.getElementsByTagName("include-param");  
    113.                     if(temp!=null && temp.getLength()>0){  
    114.                         for(int m=0;m<temp.getLength();m++){  
    115.                             Node paramNode=(temp.item(m)).getFirstChild();  
    116.                             if(paramNode!=null){  
    117.                                 String paramName=paramNode.getNodeValue().trim();  
    118.                                 if(paramName.length()>0){  
    119.                                     filtParamList.add(paramName);  
    120.                                 }  
    121.                             }  
    122.                               
    123.                         }  
    124.                           
    125.                     }  
    126.                     //一定得将url转换为小写  
    127.                     urlPatternMap.put(urlPattern.toLowerCase(), filtParamList);  
    128.                 }  
    129.             }  
    130.         }  
    131.           
    132.         //----------------------  
    133.     }  
    134.       
    135.     public static HttpServletRequest wrapRequest(HttpServletRequest httpRequest){  
    136.         if(httpRequest instanceof XssHttpRequestWrapper){  
    137. //          log.info("httpRequest instanceof XssHttpRequestWrapper");  
    138.             //include/forword指令会重新进入此Filter  
    139.             XssHttpRequestWrapper temp=(XssHttpRequestWrapper)httpRequest;  
    140.             //include指令会增加参数,这里需要清理掉缓存  
    141.             temp.refiltParams();  
    142.             return temp;  
    143.         }else{  
    144. //          log.info("httpRequest is not instanceof XssHttpRequestWrapper");  
    145.             return httpRequest;  
    146.         }  
    147.     }  
    148.       
    149.     public static List getFiltParamNames(String url){  
    150.         //获取需要xss过滤的参数  
    151.         url = url.toLowerCase();  
    152.         List paramNameList = (ArrayList) urlPatternMap.get(url);  
    153.         if(paramNameList==null || paramNameList.size()==0){  
    154.             return null;  
    155.         }  
    156.         return paramNameList;  
    157.     }  
    158.       
    159.     public static void filtRequestParams(Map params,String servletPath){  
    160.         long t1=System.currentTimeMillis();  
    161.         //得到需要过滤的参数名列表,如果列表是空的,则表示过滤所有参数  
    162.         List filtParamNames=XssSecurityManager.getFiltParamNames(servletPath);  
    163.         filtRequestParams(params, filtParamNames);  
    164.     }  
    165.       
    166.     public static void filtRequestParams(Map params,List filtParamNames){  
    167.         // 获取当前参数集  
    168.         Set parameterNames = params.keySet();  
    169.         Iterator it = parameterNames.iterator();  
    170.         //得到需要过滤的参数名列表,如果列表是空的,则表示过滤所有参数  
    171.           
    172.         while (it.hasNext()) {  
    173.             String paramName = (String) it.next();  
    174.             if(filtParamNames==null || filtParamNames.contains(paramName) ){  
    175.                 String[] values = (String[])params.get(paramName);  
    176.                 proceedXss(values);  
    177.             }  
    178.         }  
    179.     }  
    180.   
    181.       
    182.   
    183.     /** 
    184.      * 对参数进行防止xss漏洞处理 
    185.      *  
    186.      * @param value 
    187.      * @return 
    188.      */  
    189.     private static void proceedXss(String[] values) {  
    190.         for (int i = 0; i < values.length; ++i) {  
    191.             String value = values[i];  
    192.             if (!isNullStr(value)) {  
    193.                 values[i] = replaceSpecialChars(values[i]);  
    194.             }  
    195.         }  
    196.     }  
    197.   
    198.     /** 
    199.      * 替换非法字符以及危险关键字 
    200.      *  
    201.      * @param str 
    202.      * @return 
    203.      */  
    204.     private static String replaceSpecialChars(String str) {  
    205.         for (int j = 0; j < INVALID_CHARS.length; ++j) {  
    206.             if (str.indexOf(INVALID_CHARS[j]) >= 0) {  
    207.                 str = str.replace(INVALID_CHARS[j], VALID_CHARS[j]);  
    208.             }  
    209.         }  
    210.         str=str.trim();  
    211.         for (int i = 0; i < DANGEROUS_TOKENS.length; ++i) {  
    212.             str = DANGEROUS_TOKENS[i].matcher(str).replaceAll(  
    213.                     DANGEROUS_TOKEN_REPLACEMENTS[i]);  
    214.         }  
    215.   
    216.         return str;  
    217.     }  
    218.   
    219.     /** 
    220.      * 判断是否为空串,建议放到某个工具类中 
    221.      *  
    222.      * @param value 
    223.      * @return 
    224.      */  
    225.     private static boolean isNullStr(String value) {  
    226.         return value == null || value.trim().length()==0;  
    227.     }  
    228.       
    229.     public static void main(String args[]) throws Exception{  
    230.         Map datas=new HashMap();  
    231.         String paramName="test";  
    232.         datas.put(paramName,new String[]{ "Javascript:<script>alert(‘yes‘);</script>"});  
    233.         filtRequestParams(datas,"/test/sample.do");  
    234.         System.out.println(((String[])datas.get(paramName))[0]);  
    235.     }  
    236.       
    237.       
    238. }  

以上是关于Java Filter过滤xss注入非法参数的方法的主要内容,如果未能解决你的问题,请参考以下文章

SpringBoot整合XssFilter,Jsoup等实现请求参数的过滤,处理Xss攻击及sql注入

TP5框架 《防sql注入、防xss攻击》

JAVA特殊字符过滤方法

java过滤非法字符的filter

关于CI xss进攻和sql注入的防范问题

Java防止SQL注入2(通过filter过滤器功能进行拦截)