URLEncoder.encode(字符串,“UTF-8”)validation不好吗?

在我的J2EE / Java代码的一部分中,我对getRequestURI()的输出执行URLEncoding以清理它以防止XSS攻击,但Fortify SCA认为validation不良。

为什么?

关键是您需要将HTML特殊字符转换为HTML实体。 这也称为“HTML转义”或“XML转义”。 基本上,字符<>"&'需要替换为<>" &'

URL编码不会这样做。 URL编码将URL特殊字符转换为百分比编码值。 这不是HTML转义。

对于Web应用程序,HTML转义通常在视图侧完成,正好在那里您重新显示用户控制的输入。 对于Java EE Web应用程序,这取决于您正在使用的视图技术。

  1. 如果webapp使用现代Facelets视图技术,那么您不需要自己转义它。 Facelets已经隐含地这样做了。

  2. 如果webapp使用的是旧版JSP视图技术,那么您需要确保使用JSTL 标记或fn:escapeXml()函数重新显示用户控制的输入。

       
  3. 如果webapp非常遗留或设计不好并使用servlet或scriptlet打印HTML,那么你就会遇到更大的问题。 没有内置标记或函数,更不用说可以转义HTML实体的Java方法了。 您应该自己编写一些escape()方法,或者使用Apache Commons Lang StringEscapeUtils#escapeHtml() 。 然后,您需要确保在打印用户控制输入的任何地方使用它。

     out.print("

    " + StringEscapeUtils.escapeHtml(request.getParameter("foo")) + "

    ");

    更好的方法是重新设计遗留的webapp以将JSP与JSTL结合使用。

URL编码不会影响某些重要字符,包括单引号( ' )和括号,因此URL编码将传递未更改的某些有效负载。

例如,

 onload'alert(String.fromCharCode(120))' 

某些浏览器会将其视为有效属性,在注入标记内时可能导致代码执行。

避免XSS的最佳方法是将所有不受信任的输入视为纯文本,然后在编写输出时,将所有纯文本正确编码为输出上的相应类型。

如果要将输入过滤为额外的安全层,请确保filter将所有引号(包括反向标记)和括号视为可能的代码,并禁止它们,除非对该输入有意义。