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应用程序,这取决于您正在使用的视图技术。
-
如果webapp使用现代Facelets视图技术,那么您不需要自己转义它。 Facelets已经隐含地这样做了。
-
如果webapp使用的是旧版JSP视图技术,那么您需要确保使用JSTL
标记或fn:escapeXml()
函数重新显示用户控制的输入。 -
如果webapp非常遗留或设计不好并使用servlet或scriptlet打印HTML,那么你就会遇到更大的问题。 没有内置标记或函数,更不用说可以转义HTML实体的Java方法了。 您应该自己编写一些
escape()
方法,或者使用Apache Commons LangStringEscapeUtils#escapeHtml()
。 然后,您需要确保在打印用户控制输入的任何地方使用它。out.print("
" + StringEscapeUtils.escapeHtml(request.getParameter("foo")) + "
");更好的方法是重新设计遗留的webapp以将JSP与JSTL结合使用。
URL编码不会影响某些重要字符,包括单引号( '
)和括号,因此URL编码将传递未更改的某些有效负载。
例如,
onload'alert(String.fromCharCode(120))'
某些浏览器会将其视为有效属性,在注入标记内时可能导致代码执行。
避免XSS的最佳方法是将所有不受信任的输入视为纯文本,然后在编写输出时,将所有纯文本正确编码为输出上的相应类型。
如果要将输入过滤为额外的安全层,请确保filter将所有引号(包括反向标记)和括号视为可能的代码,并禁止它们,除非对该输入有意义。