如何使用filter执行输出编码以防止XSS?

我在servlet中使用以下代码:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { PrintWriter out=response.getWriter(); response.setContentType("text/html"); out.println(""); out.println(""); out.println("alert(1)"); out.println(""); out.println(""); } 

并遵循filter的代码:

 public class SampleFilter implements Filter { protected FilterConfig config; public void init(FilterConfig config) throws ServletException { this.config = config; } public void destroy() { } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException { long startTime = System.currentTimeMillis(); ServletResponse newResponse = response; if (request instanceof HttpServletRequest) { System.out.println("in filter if1"); newResponse = new CharResponseWrapper((HttpServletResponse) response); } System.out.println("after filter if1"); chain.doFilter(request, newResponse); long elapsed = System.currentTimeMillis() - startTime; if (newResponse instanceof CharResponseWrapper) { System.out.println("in filter if2"); String text = newResponse.toString(); if (text != null) { text = SampleFilter.HTMLEntityEncode(text);//.toUpperCase(); response.getWriter().write(text); } } System.out.println("after filter if2"); config.getServletContext().log(" took " + elapsed + " ms"); System.out.println(elapsed); } private static String HTMLEntityEncode(String input) { StringBuffer sb = new StringBuffer(); for (int i = 0; i < input.length(); i++) { char ch = input.charAt(i); if (Character.isLetterOrDigit(ch) || Character.isWhitespace(ch)) { sb.append(ch); } else { sb.append("&#" + (int)ch + ";"); } } return sb.toString(); } 

}

我想在浏览器中获取以下显示数据:

 alert(1) 

而我正在得到

   alert(1)   

在浏览器中。

任何帮助都会很棒。

不要这么做。 只需使用JSP生成HTML输出。 JSP标准标记库( JSTL )提供了内置方法,可以从标记和${fn:escapeXml()}函数的XSS攻击漏洞中转义用户控制的数据。

 

Welcome, !

...

他们将逃脱预定义的XML实体,如< by > 这样它就变得完全无害了。

Servlet不是为生成HTML输出而设计的。 它们的设计目的是控制请求/响应。

也可以看看:

  • JSP / Servlet Web应用程序中的XSS预防

在尝试阻止XSS攻击时,您必须将有效代码与潜在危险部分从有效表达式中分离出来。 有不同的技术来实现这一目标:

转义绑定数据:在这种情况下,您必须使用某种模板技术。 在temeplate中定义的任何内容都被认为是安全的。 在最简单的情况下,所有绑定数据都被认为是危险的,因此被转义。 制作这个简单的一个解决方案是Snippetory 。 (是的,我开发了。你可以从Sourceforge或maven repo获得它)模板可能如下所示:

    $attack $text   

然后绑定代码可能如下所示:

 Template page = Syntaxes.FLUYT_X.readResource("template.html") .encoding(Encodings.html); page.set("attack", ""); page.set("text", "text <--> escaping"); page.render(response.getWriter()); 

然而,缺点是整个输出处理必须以严格的方式完成。 但我认为对于认真的项目来说,这是最重要的方式。

现在一些可以在处理之后使用的方法,但通常与转义绑定数据结合使用,以实现Stackoverflow上的编辑器字段等复杂事物:

白名单:基本上你分析数据(可能使用html解析器)并逃避你放在白名单上的标签不属于的一切。 并删除您不允许的每个属性。 这非常安全,但也非常严格。 另外它非常复杂,所以我不能在这里提供一个例子。

黑名单:几乎相同,只是你通过你的vlack清单上没有的东西。 如果你忘了一些危险的攻击仍然可能。

在你的情况下使用填充是不可能的,因为它无法将合法内容与已注入的任何内容分开。 可以通过过滤输入而不是输出来应用针对xss的启发式黑盒防御。

我已经为Jersey REST API实现了一个XSSfilter。 可以轻松提取代码并将其应用于标准Java Filter。

大多数人建议对输出进行编码,但由于我们的数据可以通过JavaScript API访问,并且无法保证我们的客户会过滤掉XSS漏洞,因此我们选择过滤掉输入中的XSS漏洞。 这种方法的另一个好处是过滤完成一次,而不是每次输出数据。

请注意,filter需要与JSR 303的@SafeHtml批注一起使用,以确保正确过滤POST数据的内容。

我在我的博客上记录了这一点: http : //codehustler.org/blog/jersey-cross-site-scripting-xss-filter-for-java-web-apps/