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") 是一个糟糕的验证吗?的主要内容,如果未能解决你的问题,请参考以下文章

URLEncoder.encode 错误怎么解决

OpenSource就是好!

java的web开发中URLEncoder.encode方法

HttpPost过程中使用的URLEncoder.encode(something, encode)

SpringBoot解决redirect参数中文乱码问题

javaweb使用cookie存取中文以及读取中文