3

我在 servlet 中使用以下代码:

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


    out.println("<html>");
    out.println("<body>");
    out.println("<script>alert(1)</script>");
    out.println("</body>");
    out.println("</html>");
}

过滤器的以下代码:

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();

  }

}

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

<script>alert(1)</script>

而是我得到

<html>
<body>
<script>alert(1)</script>
</body>
</html>

在浏览器中。

任何帮助都会很棒。

4

4 回答 4

3

在尝试防止 XSS 攻击时,您必须将有效代码与潜在危险部分与有效表达式分开。有不同的技术可以实现这一点:

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

 <html>
   <body>
     $attack
     $text
   </body>
 </html>

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

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

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

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

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

黑名单:几乎一样,只是你让不在你的 vlack 名单上的东西。如果你忘记了一些危险的攻击仍然可能。

于 2013-03-29T10:12:19.293 回答
3

不要以艰难的方式去做。只需使用JSP生成 HTML 输出。JSP 标准标签库 ( JSTL ) 提供内置的方法来将用户控制的数据从<c:out>标签和${fn:escapeXml()}函数风格的 XSS 攻击漏洞中逃脱。

<p>Welcome, <c:out value="${user.name}" />!</p>
...
<input type="text" name="foo" value="${fn:escapeXml(param.foo)}" />

它们会像by这样转义预定义的 XML 实体,使其变得完全无害。<&gt;

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

也可以看看:

于 2013-03-31T01:16:48.490 回答
1

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

于 2013-03-29T10:24:41.253 回答
1

我已经为 Jersey REST API 实现了 XSS 过滤器。可以轻松提取代码并将其应用于标准 Java 过滤器。

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

请注意,过滤器需要与 JSR 303 的 @SafeHtml 注解结合使用,以确保正确过滤 POST 数据的内容。

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

于 2013-05-15T13:44:34.327 回答