在我的J2EE / java代码的一部分中,我对getRequestURI()
的输出执行URLEncoding来清理它以防止XSS攻击,但Fortify SCA认为验证不佳。
为什么?
答案 0 :(得分:6)
关键是您需要将HTML特殊字符转换为HTML实体。这也称为“HTML转义”或“XML转义”。基本上,字符<
,>
,"
,&
和'
需要替换为<
,>
, "
,&
和'
。
网址编码不会这样做。 URL编码将URL特殊字符转换为百分比编码值。这不是HTML转义。
对于Web应用程序,HTML转义通常在视图侧完成,正是在那里您重新显示用户控制的输入。对于Java EE Web应用程序,这取决于您正在使用的视图技术。
如果webapp使用的是现代Facelets视图技术,那么您无需自行转义。 Facelets已经隐含地这样做了。
如果webapp使用的是旧版JSP视图技术,那么您需要确保使用JSTL <c:out>
标记或fn:escapeXml()
函数重新显示用户控制的输入。
<c:out value="${bean.foo}" />
<input type="text" name="foo" value="${fn:escapeXml(param.foo)}" />
如果webapp设计非常遗留或设计不当并使用servlet或 scriptlet 来打印HTML,那么你就会遇到更大的问题。没有内置标记或函数,更不用说可以转义HTML实体的Java方法了。您应该自己编写一些escape()
方法,或者使用Apache Commons Lang StringEscapeUtils#escapeHtml()
。然后,您需要确保在打印用户控制输入的任何地方使用它。
out.print("<p>" + StringEscapeUtils.escapeHtml(request.getParameter("foo")) + "</p>");
更好的方法是重新设计遗留的webapp以将JSP与JSTL一起使用。
答案 1 :(得分:0)
URL编码不会影响某些重要字符,包括单引号('
)和括号,因此URL编码将传递未更改的某些有效负载。
例如,
onload'alert(String.fromCharCode(120))'
某些浏览器将视为有效属性,在注入标记内时可能导致代码执行。
避免XSS的最佳方法是将所有不受信任的输入视为纯文本,然后在编写输出时,将所有纯文本正确编码为输出上的相应类型。
如果要将输入过滤为额外的安全层,请确保过滤器将所有引号(包括反向标记)和括号视为可能的代码,并禁止它们,除非对该输入有意义。