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

来源:互联网 发布:长春java培训 编辑:程序博客网 时间:2024/06/04 18:54

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.       


0 0
原创粉丝点击