2015-10-05 78 views
3

我在过滤/修改Post和Put调用,以确保用户提供的所有参数都从HTML和JS代码中过滤掉,以防止XSS攻击。我想确保这是在API级别实现的,所以无论使用什么客户端,它都会受到保护。如何修改泽西岛2中的QueryParam和PathParam

使用Jersey 1.x,通过在与请求的servlet匹配之前实现ContainerRequestFilter并修改request.getQueryParameters(),这是可能的。例如:http://codehustler.org/blog/jersey-cross-site-scripting-xss-filter-for-java-web-apps/

然而,对Jersey 2来说,由于我们不能再获取QueryParameters()或getPathParameters(),而实现相同的接口是不可能的,相反,我们只能getUriInfo(),但它没用因为查询参数是不可变的。我查看了泽西的Filters and Interceptors,但不幸的是他们仅限于访问头文件和cookie。

我花了很多时间研究,但我找不到我在找什么。

是否有另一种方法来筛选路径和查询参数?有什么我失踪?

谢谢!

回答

2

我已在下面添加了一个适用于Jersey 2.x的筛选器。但是,它没有执行Cookie的XSS修复,因为我还没有找到修改这些的方法。

重要的是要注意,这需要结合使用@SafeHtml POJO属性来清理这些值。

@PreMatching 
public class XSSFilter implements ContainerRequestFilter 
{ 
    /** 
    * @see ContainerRequestFilter#filter(ContainerRequest) 
    */ 
    @Override 
    public void filter(ContainerRequestContext request) 
    { 
     cleanQueryParams(request); 
     cleanHeaders(request.getHeaders()); 
    } 


    /** 
    * Replace the existing query parameters with ones stripped of XSS vulnerabilities 
    * @param request 
    */ 
    private void cleanQueryParams(ContainerRequestContext request) 
    { 
     UriBuilder builder = request.getUriInfo().getRequestUriBuilder(); 
     MultivaluedMap<String, String> queries = request.getUriInfo().getQueryParameters(); 

     for(Map.Entry<String, List<String>> query : queries.entrySet()) 
     { 
      String key = query.getKey(); 
      List<String> values = query.getValue(); 

      builder.replaceQueryParam(key); 
      for(String value : values) { 
       builder.replaceQueryParam(key, Utils.stripXSS(value)); 
      } 

     } 

     request.setRequestUri(builder.build()); 
    } 


    /** 
    * Replace the existing headers with ones stripped of XSS vulnerabilities 
    * @param headers 
    */ 
    private void cleanHeaders(MultivaluedMap<String, String> headers) 
    { 
     for(Map.Entry<String, List<String>> header : headers.entrySet()) 
     { 
      String key = header.getKey(); 
      List<String> values = header.getValue(); 

      List<String> cleanValues = new ArrayList<String>(); 
      for(String value : values) { 
       cleanValues.add(Utils.stripXSS(value)); 
      } 

      headers.put(key, cleanValues); 
     } 
    } 
} 

的stripXSS职能如下:

/** 
* Strips any potential XSS threats out of the value 
* 
* @param value 
* @return 
*/ 
public static String stripXSS(String value) 
{ 
    return stripXSS(value, Whitelist.none()); 
} 


/** 
* Strips any potential XSS threats out of the value excluding 
* the white listed HTML 
* 
* @param value 
* @param whitelist 
* @return 
*/ 
public static String stripXSS(String value, Whitelist whitelist) 
{ 
    if(StringUtils.isBlank(value)) 
     return value; 

    // Use the ESAPI library to avoid encoded attacks. 
    value = ESAPI.encoder().canonicalize(value); 

    // Avoid null characters 
    value = value.replaceAll("\0", ""); 

    // Clean out HTML 
    Document.OutputSettings outputSettings = new Document.OutputSettings(); 
    outputSettings.escapeMode(EscapeMode.xhtml); 
    outputSettings.prettyPrint(false); 
    value = Jsoup.clean(value, "", whitelist, outputSettings); 

    return value; 
} 

还更新了原来的职位:http://codehustler.org/blog/jersey-cross-site-scripting-xss-filter-for-java-web-apps/

0

您可以使用ContainerRequestFilter,构造一个新的URI(基于现有的URI),并通过setRequestUri方法在ContainerRequestContext中设置URI。

@PreMatching 
public class MyFilter implements ContainerRequestFilter { 

    @Override 
    public void filter(ContainerRequestContext requestContext) throws IOException { 

     UriBuilder builder = requestContext.getUriInfo().getRequestUriBuilder(); 

     // Replace a query param 
     builder.replaceQueryParam("foo", "bar"); 

     // Remove a query param 
     builder.replaceQueryParam("baz"); 

     // Replace path 
     builder.replacePath("newPath"); 

     requestContext.setRequestUri(builder.build()); 
    } 
} 

有了然而这种方法,我还没有找到一种方法来代替单个通道的基础上从匹配的球衣资源的URI模板PARAM名PARAMS,因为“setRequestUri”仅在前期资源匹配阶段允许的。所以整个路径需要被替换。