基于Antisamy项目实现防XSS攻击

    最近项目上线,请第三方公司进行了一次渗透性测试,被发现存在多处XSS攻击。由于我们对于URL的Get请求已经通过URLFilter进行了特殊字符过滤,Get请求的漏洞已经被封堵,但是对于Post请求考虑到我们项目存在表单提交,富文本编辑等功能,不敢贸然的使用Filter对关键字进行过滤。

为了解决上述问题,我们采用了OWASP的一个开源的项目AntiSamy来彻底解决XSS攻击问题。AntiSamy是一个可以确保用户输入的HTML、CSS、JavaScript符合规范的API。它确保了用户无法在HTML中提交恶意代码,而这些恶意代码通常被输入到个人资料、评论等会被服务端存储的数据中。

AntiSamy的下载地址:

 官方网站:https://www.owasp.org/index.php/Category:OWASP_AntiSamy_Project

          项目地址:https://code.google.com/p/owaspantisamy/downloads/list

 我们项目使用的Java,除了antisamy-1.5.3.jar包外,还需要下述jar包。

基于Antisamy项目实现防XSS攻击_第1张图片

AntiSamy的使用如下:

定义一个XssFilter的Class,该类必须实现Filter类,在XssFilter类中实现doFilter函数。将策略文件放到和pom.xml同级目录下,然后开始编写XssFilter。

[java]  view plain  copy
 
  1.    public class XssFilter implements Filter {  
  2. @SuppressWarnings("unused")  
  3. private FilterConfig filterConfig;  
  4. public void destroy() {  
  5.     this.filterConfig = null;  
  6. }  
  7. public void doFilter(ServletRequest request, ServletResponse response,  
  8.         FilterChain chain) throws IOException, ServletException {  
  9.     chain.doFilter(new XssRequestWrapper((HttpServletRequest) request), response);  
  10. }  
  11. public void init(FilterConfig filterConfig) throws ServletException {  
  12.     this.filterConfig = filterConfig;  
  13. }     
  14.    }  
我们需要重写request,新建一个类XssRequestWrapper,继承HttpServletRequestWrapper,需要重写getParameter(String param), getParameterValues(String param)以及getHeader(String param)方法,以及过滤非法html方法xssClean()

[java]  view plain  copy
 
  1. public class XssRequestWrapper extends HttpServletRequestWrapper {  
  2.       
  3.     private static Policy policy = null;  
  4.       
  5.     static{  
  6.         //String path = URLUtility.getClassPath(XssRequestWrapper.class)+File.separator+"antisamy-anythinggoes-1.4.4.xml";  
  7.         String path =XssRequestWrapper.class.getClassLoader().getResource("antisamy-anythinggoes-1.4.4.xml").getFile();  
  8.         System.out.println("policy_filepath:"+path);  
  9.         if(path.startsWith("file")){  
  10.             path = path.substring(6);  
  11.         }  
  12.          try {  
  13.             policy = Policy.getInstance(path);  
  14.         } catch (PolicyException e) {  
  15.             e.printStackTrace();  
  16.         }  
  17.     }  
  18.   
  19.     public XssRequestWrapper(HttpServletRequest request) {  
  20.         super(request);  
  21.     }  
  22.       
  23.     @SuppressWarnings("rawtypes")  
  24.     public Map<String,String[]> getParameterMap(){  
  25.         Map<String,String[]> request_map = super.getParameterMap();  
  26.         Iterator iterator = request_map.entrySet().iterator();  
  27.         System.out.println("request_map"+request_map.size());  
  28.         while(iterator.hasNext()){  
  29.             Map.Entry me = (Map.Entry)iterator.next();  
  30.             //System.out.println(me.getKey()+":");  
  31.             String[] values = (String[])me.getValue();  
  32.             for(int i = 0 ; i < values.length ; i++){  
  33.                 System.out.println(values[i]);  
  34.                 values[i] = xssClean(values[i]);  
  35.             }  
  36.         }  
  37.         return request_map;  
  38.     }  
  39.      public String[] getParameterValues(String paramString)  
  40.       {  
  41.         String[] arrayOfString1 = super.getParameterValues(paramString);  
  42.         if (arrayOfString1 == null)  
  43.           return null;  
  44.         int i = arrayOfString1.length;  
  45.         String[] arrayOfString2 = new String[i];  
  46.         for (int j = 0; j < i; j++)  
  47.           arrayOfString2[j] = xssClean(arrayOfString1[j]);  
  48.         return arrayOfString2;  
  49.       }  
  50.   
  51.       public String getParameter(String paramString)  
  52.       {  
  53.         String str = super.getParameter(paramString);  
  54.         if (str == null)  
  55.           return null;  
  56.         return xssClean(str);  
  57.       }  
  58.   
  59.       public String getHeader(String paramString)  
  60.       {  
  61.         String str = super.getHeader(paramString);  
  62.         if (str == null)  
  63.           return null;  
  64.         return xssClean(str);  
  65.       }  
  66.         
  67.         
  68.     private String xssClean(String value) {  
  69.         AntiSamy antiSamy = new AntiSamy();  
  70.         try {  
  71.             //CleanResults cr = antiSamy.scan(dirtyInput, policyFilePath);   
  72.             final CleanResults cr = antiSamy.scan(value, policy);  
  73.             //安全的HTML输出  
  74.             return cr.getCleanHTML();  
  75.         } catch (ScanException e) {  
  76.             e.printStackTrace();  
  77.         } catch (PolicyException e) {  
  78.             e.printStackTrace();  
  79.         }  
  80.         return value;  
  81.     }  
  82. }  
在我们使用AntiSamy进行测试时,发现确实能够有效的控制xss攻击,用户的非法输入全部被删除或替换了,但是也发现会把“&nbsp;”转换成乱码,把双引号转换成"&quot;"

为了解决这两个错误转换,我们修改了xssClean(String value)方法。

[java]  view plain  copy
 
  1. <p align="left">  
  2. </p>  
基于Antisamy项目实现防XSS攻击_第2张图片

你可能感兴趣的:(spring,Web,xss,CSRF)