使用filter过滤xss攻击

    xiaoxiao2021-03-25  68

    使用filter过滤xss攻击

    filter实现脚注入攻击过滤源码 

     

    先说一下实现思路:

    1. 使用正则表达式的方式实现脚本过滤,这个方法准确率较高,但是可能根据不能的要求会变动;

    2. 为了保证配置灵活(包括正则表达式灵活),使用xml配置文件的方式记录配置信息,配置信息包含是否开启校验、是否记录日志、是否中断请求、是否替换脚本字符等;

    3. 为保证xml与正则表达式的特殊字符不冲突,使用<![CDATA[]]>标签存放正则表达式,但是在类中需要特殊处理;

    4. 通过继承HttpRequestWrapper的方式实现request中header和parameter信息过滤;

    5. xml解析使用dom4j,稍后会对这个工具的使用写一篇文章,暂时辛苦大家去网站查找资料(这篇文章很不错http://www.ibm.com/developerworks/cn/xml/x-dom4j.html);

    6. 使用XSSSecurityManager类实现配置信息加载和处理,XSSSecurityConfig记录匹配信息,XSSSecurityCon标识程序所需常量;

     

    附件包含源码,如果能帮我改进更好

     

     

     

    Java代码   package com.sg.security;    import java.io.IOException;  import java.util.Enumeration;  import java.util.Map;  import java.util.Set;    import javax.servlet.ServletException;  import javax.servlet.http.HttpServletRequest;  import javax.servlet.http.HttpServletRequestWrapper;  import javax.servlet.http.HttpServletResponse;      /**  * @author winnie  * @date   * @describe request信息封装类,用于判断、处理request请求中特殊字符  */  public class XSSHttpRequestWrapper extends HttpServletRequestWrapper {            /**      * 封装http请求      * @param request      */      public XSSHttpRequestWrapper(HttpServletRequest request) {          super(request);      }            @Override      public String getHeader(String name) {          String value = super.getHeader(name);          // 若开启特殊字符替换,对特殊字符进行替换          if(XSSSecurityConfig.REPLACE){              XSSSecurityManager.securityReplace(name);          }          return value;      }        @Override      public String getParameter(String name) {          String value = super.getParameter(name);          // 若开启特殊字符替换,对特殊字符进行替换          if(XSSSecurityConfig.REPLACE){              XSSSecurityManager.securityReplace(name);          }          return value;      }        /**      * 没有违规的数据,就返回false;      *       * @return      */      @SuppressWarnings("unchecked")      private boolean checkHeader(){          Enumeration<String> headerParams = this.getHeaderNames();          while(headerParams.hasMoreElements()){              String headerName = headerParams.nextElement();              String headerValue = this.getHeader(headerName);              if(XSSSecurityManager.matches(headerValue)){                  return true;              }          }          return false;      }            /**      * 没有违规的数据,就返回false;      *       * @return      */      @SuppressWarnings("unchecked")      private boolean checkParameter(){          Map<String,Object> submitParams = this.getParameterMap();          Set<String> submitNames = submitParams.keySet();          for(String submitName : submitNames){              Object submitValues = submitParams.get(submitName);              if(submitValues instanceof String){                  if(XSSSecurityManager.matches((String)submitValues)){                      return true;                  }              }else if(submitValues instanceof String[]){                  for(String submitValue : (String[])submitValues){                      if(XSSSecurityManager.matches((String)submitValue)){                          return true;                      }                  }              }          }          return false;      }                 /**      * 没有违规的数据,就返回false;      * 若存在违规数据,根据配置信息判断是否跳转到错误页面      * @param response      * @return      * @throws IOException       * @throws ServletException       */      public boolean validateParameter(HttpServletResponse response) throws ServletException, IOException{          // 开始header校验,对header信息进行校验          if(XSSSecurityConfig.IS_CHECK_HEADER){              if(this.checkHeader()){                  return true;              }          }          // 开始parameter校验,对parameter信息进行校验          if(XSSSecurityConfig.IS_CHECK_PARAMETER){              if(this.checkParameter()){                  return true;              }          }          return false;      }        }  

     

     

    Java代码   /**  *   */  package com.sg.security;    import java.io.IOException;    import javax.servlet.Filter;  import javax.servlet.FilterChain;  import javax.servlet.FilterConfig;  import javax.servlet.ServletException;  import javax.servlet.ServletRequest;  import javax.servlet.ServletResponse;  import javax.servlet.http.HttpServletRequest;  import javax.servlet.http.HttpServletResponse;    import org.apache.log4j.Logger;      /**  * @author winnie  * @date   * @describe 安全信息审核类  */  public class XSSSecurityFilter implements Filter{        private static Logger logger = Logger.getLogger(XSSSecurityFilter.class);            /**      * 销毁操作      */      public void destroy() {          logger.info("XSSSecurityFilter destroy() begin");          XSSSecurityManager.destroy();          logger.info("XSSSecurityFilter destroy() end");      }        /**      * 安全审核      * 读取配置信息      */      public void doFilter(ServletRequest request, ServletResponse response,              FilterChain chain) throws IOException, ServletException {          // 判断是否使用HTTP          checkRequestResponse(request, response);          // 转型          HttpServletRequest httpRequest = (HttpServletRequest) request;          HttpServletResponse httpResponse = (HttpServletResponse) response;          // http信息封装类          XSSHttpRequestWrapper xssRequest = new XSSHttpRequestWrapper(httpRequest);                    // 对request信息进行封装并进行校验工作,若校验失败(含非法字符),根据配置信息进行日志记录和请求中断处理          if(xssRequest.validateParameter(httpResponse)){              if(XSSSecurityConfig.IS_LOG){                  // 记录攻击访问日志                  // 可使用数据库、日志、文件等方式              }              if(XSSSecurityConfig.IS_CHAIN){                  httpRequest.getRequestDispatcher(XSSSecurityCon.FILTER_ERROR_PAGE).forward( httpRequest, httpResponse);                  return;              }          }          chain.doFilter(xssRequest, response);      }        /**      * 初始化操作      */      public void init(FilterConfig filterConfig) throws ServletException {          XSSSecurityManager.init(filterConfig);      }        /**      * 判断Request ,Response 类型      * @param request      *            ServletRequest      * @param response      *            ServletResponse      * @throws ServletException       */      private void checkRequestResponse(ServletRequest request,              ServletResponse response) throws ServletException {          if (!(request instanceof HttpServletRequest)) {              throw new ServletException("Can only process HttpServletRequest");            }          if (!(response instanceof HttpServletResponse)) {              throw new ServletException("Can only process HttpServletResponse");          }      }  }  

     

    Java代码   /**  *   */  package com.sg.security;    import java.util.Iterator;  import java.util.regex.Pattern;    import javax.servlet.FilterConfig;    import org.apache.log4j.Logger;  import org.dom4j.DocumentException;  import org.dom4j.Element;  import org.dom4j.io.SAXReader;    /**  * @author winnie  * @date   * @describe 安全过滤配置管理类,由XSSSecurityManger修改  */  public class XSSSecurityManager {            private static Logger logger = Logger.getLogger(XSSSecurityManager.class);            /**      * REGEX:校验正则表达式      */      public static String REGEX;             /**      * 特殊字符匹配      */      private static Pattern XSS_PATTERN ;                  private XSSSecurityManager(){          //不可被实例化      }            public static void init(FilterConfig config){          logger.info("XSSSecurityManager init(FilterConfig config) begin");          //初始化过滤配置文件          String xssPath = config.getServletContext().getRealPath("/")                  + config.getInitParameter("securityconfig");                    // 初始化安全过滤配置          try {              if(initConfig(xssPath)){                  // 生成匹配器                  XSS_PATTERN = Pattern.compile(REGEX);              }          } catch (DocumentException e) {              logger.error("安全过滤配置文件xss_security_config.xml加载异常",e);          }          logger.info("XSSSecurityManager init(FilterConfig config) end");      }            /**      * 读取安全审核配置文件xss_security_config.xml      * 设置XSSSecurityConfig配置信息      * @param path 配置文件地址 eg C:/apache-tomcat-6.0.33/webapps/security_filter/WebRoot/config/xss/xss_security_config.xml      * @return       * @throws DocumentException      */      @SuppressWarnings("unchecked")      public static boolean initConfig(String path) throws DocumentException {          logger.info("XSSSecurityManager.initConfig(String path) begin");          Element superElement = new SAXReader().read(path).getRootElement();          XSSSecurityConfig.IS_CHECK_HEADER = new Boolean(getEleValue(superElement,XSSSecurityCon.IS_CHECK_HEADER));          XSSSecurityConfig.IS_CHECK_PARAMETER = new Boolean(getEleValue(superElement,XSSSecurityCon.IS_CHECK_PARAMETER));          XSSSecurityConfig.IS_LOG = new Boolean(getEleValue(superElement,XSSSecurityCon.IS_LOG));          XSSSecurityConfig.IS_CHAIN = new Boolean(getEleValue(superElement,XSSSecurityCon.IS_CHAIN));          XSSSecurityConfig.REPLACE = new Boolean(getEleValue(superElement,XSSSecurityCon.REPLACE));            Element regexEle = superElement.element(XSSSecurityCon.REGEX_LIST);                    if(regexEle != null){              Iterator<Element> regexIt = regexEle.elementIterator();              StringBuffer tempStr = new StringBuffer("^");              //xml的cdata标签传输数据时,会默认在\前加\,需要将\\替换为\              while(regexIt.hasNext()){                  Element regex = (Element)regexIt.next();                  String tmp = regex.getText();                  tmp = tmp.replaceAll("\\\\\\\\", "\\\\");                  tempStr.append(tmp);                  tempStr.append("|");              }              if(tempStr.charAt(tempStr.length()-1)=='|'){                  REGEX= tempStr.substring(0, tempStr.length()-1)+"$";                  logger.info("安全匹配规则"+REGEX);              }else{                  logger.error("安全过滤配置文件加载失败:正则表达式异常 "+tempStr.toString());                  return false;              }          }else{              logger.error("安全过滤配置文件中没有 "+XSSSecurityCon.REGEX_LIST+" 属性");              return false;          }          logger.info("XSSSecurityManager.initConfig(String path) end");          return true;        }            /**      * 从目标element中获取指定标签信息,若找不到该标签,记录错误日志      * @param element 目标节点      * @param tagName 制定标签      * @return       */      private static String getEleValue(Element element, String tagName){          if (isNullStr(element.elementText(tagName))){              logger.error("安全过滤配置文件中没有 "+XSSSecurityCon.REGEX_LIST+" 属性");          }          return element.elementText(tagName);      }            /**      * 对非法字符进行替换      * @param text      * @return      */      public static String securityReplace(String text){          if(isNullStr(text)){              return text;          }else{              return text.replaceAll(REGEX, XSSSecurityCon.REPLACEMENT);          }      }            /**      * 匹配字符是否含特殊字符      * @param text      * @return      */      public static boolean matches(String text){          if(text==null){              return false;          }          return XSS_PATTERN.matcher(text).matches();      }            /**      * 释放关键信息      */      public static void destroy(){          logger.info("XSSSecurityManager.destroy() begin");          XSS_PATTERN = null;          REGEX = null;          logger.info("XSSSecurityManager.destroy() end");      }            /**      * 判断是否为空串,建议放到某个工具类中      * @param value      * @return      */      public static boolean isNullStr(String value){          return value == null || value.trim().equals("");      }  }  

     

     

    Java代码   /**  *   */  package com.sg.security;    /**  * @author winnie  * 安全过滤配置信息类  */  public class XSSSecurityConfig {            /**      * CHECK_HEADER:是否开启header校验      */      public static boolean IS_CHECK_HEADER;             /**      * CHECK_PARAMETER:是否开启parameter校验      */      public static boolean IS_CHECK_PARAMETER;            /**      * IS_LOG:是否记录日志      */      public static boolean IS_LOG;            /**      * IS_LOG:是否中断操作      */      public static boolean IS_CHAIN;            /**      * REPLACE:是否开启替换      */      public static boolean REPLACE;          }  

     

     

    Java代码   /**  *   */  package com.sg.security;    /**  * @author winnie  * @date   * @describe  */  public class XSSSecurityCon {        /**      * 配置文件标签 isCheckHeader      */      public static String IS_CHECK_HEADER = "isCheckHeader";        /**      * 配置文件标签 isCheckParameter      */      public static String IS_CHECK_PARAMETER = "isCheckParameter";        /**      * 配置文件标签 isLog      */      public static String IS_LOG = "isLog";        /**      * 配置文件标签 isChain      */      public static String IS_CHAIN = "isChain";        /**      * 配置文件标签 replace      */      public static String REPLACE = "replace";        /**      * 配置文件标签 regexList      */      public static String REGEX_LIST = "regexList";        /**      * 替换非法字符的字符串      */      public static String REPLACEMENT = "";        /**      * FILTER_ERROR_PAGE:过滤后错误页面      */      public static String FILTER_ERROR_PAGE = "/common/filtererror.jsp";    }  

     

    xss_security_config.xml

    Xml代码   <?xml version="1.0" encoding="UTF-8"?>  <XSSConfig>      <!-- 是否进行header校验 -->      <isCheckHeader>false</isCheckHeader>      <!-- 是否进行parameter校验 -->      <isCheckParameter>true</isCheckParameter>      <!-- 是否记录日志 -->      <isLog>true</isLog>      <!-- 是否中断请求 -->      <isChain>false</isChain>      <!-- 是否开启特殊字符替换 -->      <replace>true</replace>      <!-- 是否开启特殊url校验 -->      <isCheckUrl>true</isCheckUrl>      <regexList>          <!-- 匹配含有字符: alert( ) -->          <regex><![CDATA[.*[A|a][L|l][E|e][R|r][T|t]\\s*\\(.*\\).*]]></regex>          <!-- 匹配含有字符: window.location = -->          <regex><![CDATA[.*[W|w][I|i][N|n][D|d][O|o][W|w]\\.[L|l][O|o][C|c][A|a][T|t][I|i][O|o][N|n]\\s*=.*]]></regex>          <!-- 匹配含有字符:style = x:ex pression ( ) -->          <regex><![CDATA[.*[S|s][T|t][Y|y][L|l][E|e]\\s*=.*[X|x]:[E|e][X|x].*[P|p][R|r][E|e][S|s]{1,2}[I|i][O|o][N|n]\\s*\\(.*\\).*]]></regex>          <!-- 匹配含有字符: document.cookie -->          <regex><![CDATA[.*[D|d][O|o][C|c][U|u][M|m][E|e][N|n][T|t]\\.[C|c][O|o]{2}[K|k][I|i][E|e].*]]></regex>          <!-- 匹配含有字符: eval( ) -->          <regex><![CDATA[.*[E|e][V|v][A|a][L|l]\\s*\\(.*\\).*]]></regex>          <!-- 匹配含有字符: unescape() -->          <regex><![CDATA[.*[U|u][N|n][E|e][S|s][C|c][A|a][P|p][E|e]\\s*\\(.*\\).*]]></regex>          <!-- 匹配含有字符: execscript( ) -->          <regex><![CDATA[.*[E|e][X|x][E|e][C|c][S|s][C|c][R|r][I|i][P|p][T|t]\\s*\\(.*\\).*]]></regex>          <!-- 匹配含有字符: msgbox( ) -->          <regex><![CDATA[.*[M|m][S|s][G|g][B|b][O|o][X|x]\\s*\\(.*\\).*]]></regex>          <!-- 匹配含有字符: confirm( ) -->          <regex><![CDATA[.*[C|c][O|o][N|n][F|f][I|i][R|r][M|m]\\s*\\(.*\\).*]]></regex>          <!-- 匹配含有字符: prompt( ) -->          <regex><![CDATA[.*[P|p][R|r][O|o][M|m][P|p][T|t]\\s*\\(.*\\).*]]></regex>          <!-- 匹配含有字符: <script> </script> -->          <regex><![CDATA[.*<[S|s][C|c][R|r][I|i][P|p][T|t]>.*</[S|s][C|c][R|r][I|i][P|p][T|t]>.*]]></regex>          <!-- 匹配含有字符: 含有一个符号: "  -->          <regex><![CDATA[[.&[^\"]]*\"[.&[^\"]]*]]></regex>          <!-- 匹配含有字符: 含有一个符号: '  -->          <regex><![CDATA[[.&[^']]*'[.&[^']]*]]></regex>          <!-- 匹配含有字符: 含有回车换行 和 <script> </script> -->          <regex><![CDATA[[[.&[^a]]|[|a|\n|\r\n|\r|\u0085|\u2028|\u2029]]*<[S|s][C|c][R|r][I|i][P|p][T|t]>.*</[S|s][C|c][R|r][I|i][P|p][T|t]>[[.&[^a]]|[|a|\n|\r\n|\r|\u0085|\u2028|\u2029]]*]]></regex>      </regexList>  </XSSConfig>  

     

    web.xml配置

    Xml代码   <?xml version="1.0" encoding="UTF-8"?>  <web-app version="2.5"       xmlns="http://java.sun.com/xml/ns/javaee"       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"       xsi:schemaLocation="http://java.sun.com/xml/ns/javaee       http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">    <welcome-file-list>      <welcome-file>index.jsp</welcome-file>    </welcome-file-list>      <!-- 信息安全审核 -->      <filter>          <filter-name>XSSFiler</filter-name>          <filter-class>              com.sg.security.XSSSecurityFilter          </filter-class>          <init-param>              <param-name>securityconfig</param-name>              <param-value>                  /WebRoot/config/xss/xss_security_config.xml              </param-value>          </init-param>      </filter>      <!-- 拦截请求类型 -->      <filter-mapping>          <filter-name>XSSFiler</filter-name>          <url-pattern>*.jsp</url-pattern>      </filter-mapping>      <filter-mapping>          <filter-name>XSSFiler</filter-name>          <url-pattern>*.do</url-pattern>      </filter-mapping>  </web-app> 
    转载请注明原文地址: https://ju.6miu.com/read-33690.html

    最新回复(0)