URLEncoder.encode(string, "UTF-8") 是一个糟糕的验证吗?
Posted
技术标签:
【中文标题】URLEncoder.encode(string, "UTF-8") 是一个糟糕的验证吗?【英文标题】:Is URLEncoder.encode(string, "UTF-8") a poor validation? 【发布时间】:2012-03-06 16:59:19 【问题描述】:在我的 J2EE/java 代码的一部分中,我对 getRequestURI()
的输出执行 URLEncoding 以对其进行清理以防止 XSS 攻击,但 Fortify SCA 认为验证很差。
为什么?
【问题讨论】:
这取决于您要使用该字符串的上下文。那么你在哪里输出呢? HP Fortify SCA 将其列为“验证不佳”的主要原因是编码不是验证。您应该将此视为 Fortify Medium" 问题,因为它认识到已为缓解该问题做出了一些努力。 【参考方案1】:关键是您需要将 html 特殊字符转换为 HTML 实体。这也称为“HTML 转义”或“XML 转义”。基本上,字符<
、>
、"
、&
和'
需要替换为<
、>
、"
、&
和'
。 p>
URL 编码不这样做。 URL 编码将 URL 特殊字符转换为百分比编码值。这不是 HTML 转义。
在 Web 应用程序的情况下,HTML 转义通常在视图端完成,正是在那里您重新显示用户控制的输入。对于 Java EE Web 应用程序,这取决于您使用的视图技术。
如果 web 应用程序使用现代 Facelets 视图技术,那么您不需要自己转义它。 Facelets 已经隐含地这样做了。
如果 webapp 使用旧版 JSP 视图技术,那么您需要确保使用 JSTL <c:out>
标记或 fn:escapeXml()
函数来重新显示用户控制的输入。
<c:out value="$bean.foo" />
<input type="text" name="foo" value="$fn:escapeXml(param.foo)" />
如果 web 应用程序非常陈旧或设计不佳,并且使用 servlet 或 scriptlets 来打印 HTML,那么您的问题就更大了。没有内置标签或函数,更不用说可以转义 HTML 实体的 Java 方法了。您应该自己编写一些 escape()
方法或为此使用 Apache Commons Lang StringEscapeUtils#escapeHtml()
。然后,您需要确保在打印用户控制输入的任何地方都使用它。
out.print("<p>" + StringEscapeUtils.escapeHtml(request.getParameter("foo")) + "</p>");
重新设计旧的 web 应用程序以将 JSP 与 JSTL 一起使用会更好。
【讨论】:
请注意,HTML 编码通常也会被标记为验证不佳。由于 SCA 是一种自动化工具,它对代码本身的上下文知之甚少,因此它无法知道它是否会在每个实例中防止 XSS。例如,您故意将用户输入直接放入脚本中(javascript、Python、Ruby 等等。如果它是一种脚本语言,那么它很容易受到 XSS 攻击)。【参考方案2】:URL 编码不影响某些重要字符,包括单引号 ('
) 和括号,因此 URL 编码将通过不变的某些负载。
例如,
onload'alert(String.fromCharCode(120))'
将被某些浏览器视为有效属性,当注入标签时会导致代码执行。
避免 XSS 的最佳方法是将所有不受信任的输入视为纯文本,然后在编写输出时,将所有纯文本正确编码为输出的适当类型。
如果您想过滤输入作为额外的安全层,请确保您的过滤器将所有引号(包括反引号)和括号视为可能的代码,并禁止它们,除非该输入有意义。
【讨论】:
以上是关于URLEncoder.encode(string, "UTF-8") 是一个糟糕的验证吗?的主要内容,如果未能解决你的问题,请参考以下文章
java的web开发中URLEncoder.encode方法