防止跨站点脚本的 Java 最佳实践
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1159729/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java Best Practices to Prevent Cross Site Scripting
提问by
I have gone through the OWASP top ten vulnerabilities and found that Cross-Site Scripting is the one we have to take notes. There was few way recommended solutions. One has stated that Do not use "blacklist" validation to detect XSS in input or to encode output. Searching for and replacing just a few characters (<
and >
and other similar characters or phrases such as script
) is weak and has been attacked successfully. Even an unchecked “<b>”
tag is unsafe in some contexts. XSS has a surprising number of variants that make it easy to bypass blacklist validation. Another solution said that Strong output encoding. Ensure that all user-supplied data is appropriately entity encoded (either HTML or XML depending on the output mechanism) before rendering. So, which is the best way to prevent cross site scripting to validate and replace the input or encoding the output ?
我翻遍了OWASP的十大漏洞,发现Cross-Site Scripting是我们要注意的一个。推荐的解决方案很少。有人说不要使用“黑名单”验证来检测输入中的 XSS 或编码输出。仅搜索和替换几个字符(<
以及>
其他类似字符或短语,例如script
)是很弱的,并且已被成功攻击。即使是未经检查的“<b>”
标签在某些情况下是不安全的。XSS 具有数量惊人的变体,可以轻松绕过黑名单验证。另一种解决方案是强输出编码。确保所有用户提供的数据在呈现之前都经过适当的实体编码(HTML 或 XML,具体取决于输出机制)。那么,防止跨站点脚本验证和替换输入或编码输出的最佳方法是什么?
回答by
My preference is to encode all non-alphaumeric characters as HTML numeric character entities. Since almost, if not all attacks require non-alphuneric characters (like <, ", etc) this should eliminate a large chunk of dangerous output.
我的偏好是将所有非字母数字字符编码为 HTML 数字字符实体。因为几乎,如果不是所有攻击都需要非字母字符(如 <、" 等),这应该消除大量危险的输出。
Format is &#N;, where N is the numeric value of the character (you can just cast the character to an int and concatenate with a string to get a decimal value). For example:
格式为 &#N;,其中 N 是字符的数值(您可以将字符转换为 int 并与字符串连接以获得十进制值)。例如:
// java-ish pseudocode StringBuffer safestrbuf = new StringBuffer(string.length()*4); foreach(char c : string.split() ){ if( Character.isAlphaNumeric(c) ) safestrbuf.append(c); else safestrbuf.append(""+(int)symbol);
You will also need to be sure that you are encoding immediately before outputting to the browser, to avoid double-encoding, or encoding for HTML but sending to a different location.
您还需要确保在输出到浏览器之前立即进行编码,以避免双重编码,或为 HTML 编码但发送到不同的位置。
回答by Vineet Reynolds
Use both. In fact refer a guide like the OWASP XSS Prevention cheat sheet, on the possible cases for usage of output encoding and input validation.
两者都用。事实上,请参考OWASP XSS 预防备忘单之类的指南,了解有关使用输出编码和输入验证的可能情况。
Input validation helps when you cannot rely on output encoding in certain cases. For instance, you're better off validating inputs appearing in URLs rather than encoding the URLs themselves (Apache will not serve a URL that is url-encoded). Or for that matter, validate inputs that appear in JavaScript expressions.
当您在某些情况下不能依赖输出编码时,输入验证会有所帮助。例如,您最好验证出现在 URL 中的输入,而不是对 URL 本身进行编码(Apache 不会提供经过 url 编码的 URL)。或者就此而言,验证出现在 JavaScript 表达式中的输入。
Ultimately, a simple thumb rule will help - if you do not trust user input enough or if you suspect that certain sources can result in XSS attacks despite output encoding, validate it against a whitelist.
最终,一个简单的经验法则会有所帮助 - 如果您对用户输入的信任度不够,或者如果您怀疑某些来源可能会导致 XSS 攻击,尽管输出编码,请根据白名单对其进行验证。
Do take a look at the OWASP ESAPIsource code on how the output encoders and input validators are written in a security library.
请查看OWASP ESAPI源代码,了解如何在安全库中编写输出编码器和输入验证器。
回答by BalusC
The normal practice is to HTML-escape any user-controlleddata during redisplayingin JSP, not during processingthe submitted data in servlet nor during storingin DB. In JSP you can use the JSTL(to install it, just drop jstl-1.2.jarin /WEB-INF/lib
) <c:out>
tag or fn:escapeXml
function for this. E.g.
通常的做法是在 JSP中重新显示期间对任何用户控制的数据进行 HTML 转义,而不是在 servlet中处理提交的数据期间,也不是在存储到 DB期间。在 JSP 中,您可以为此使用JSTL(安装它,只需将jstl-1.2.jar放入)标记或函数。例如/WEB-INF/lib
<c:out>
fn:escapeXml
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
...
<p>Welcome <c:out value="${user.name}" /></p>
and
和
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
...
<input name="username" value="${fn:escapeXml(param.username)}">
That's it. No need for a blacklist. Note that user-controlled data covers everythingwhich comes in by a HTTP request: the request parameters, body and headers(!!).
就是这样。不需要黑名单。请注意,用户控制的数据涵盖了 HTTP 请求传入的所有内容:请求参数、正文和标头 (!!)。
If you HTML-escape it during processing the submitted data and/or storing in DB as well, then it's all spread over the business code and/or in the database. That's only maintenance trouble and you will risk double-escapes or more when you do it at different places (e.g. &
would become &amp;
instead of &
so that the enduser would literally see &
instead of &
in view. The business code and DB are in turn not sensitive for XSS. Only the view is. You should then escape it only right therein view.
如果您在处理提交的数据和/或存储在数据库中的过程中对它进行 HTML 转义,那么它就会全部分布在业务代码和/或数据库中。这只是维护问题,当你在不同的地方做这件事时,你会冒双重逃逸或更多的风险(例如,&
将变成&amp;
而不是&
这样,最终用户会真正看到&
而不是&
在视图中。业务代码和数据库反过来对 XSS 不敏感只有该视图。然后,您应该逃避它只是在那里的视图。