Java防止跨站点脚本的最佳实践

时间:2022-12-24 12:15:31

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十大漏洞,发现跨站点脚本是我们必须记笔记的。推荐的解决方案很少。有人说过不要使用“黑名单”验证来检测输入中的XSS或编码输出。搜索和替换几个字符( <和> 以及其他类似字符或短语(如脚本))很弱,并且已成功攻击。即使是未经检查的“ ”标记在某些情况下也是不安全的。 XSS拥有数量惊人的变体,可以轻松绕过黑名单验证。另一种解决方案是强输出编码。在渲染之前,确保所有用户提供的数据都经过适当的实体编码(HTML或XML,具体取决于输出机制)。那么,这是阻止跨站点脚本验证和替换输入或编码输出的最佳方法?

3 个解决方案

#1


39  

The normal practice is to HTML-escape any user-controlled data during redisplaying in JSP, not during processing the submitted data in servlet nor during storing in DB. In JSP you can use the JSTL (to install it, just drop jstl-1.2.jar in /WEB-INF/lib) <c:out> tag or fn:escapeXml function for this. E.g.

通常的做法是在JSP中重新显示期间HTML转义任何用户控制的数据,而不是在servlet中处理提交的数据期间或在DB中存储期间。在JSP中,你可以使用JSTL(安装它,只需在/ WEB-INF / lib中删除jstl-1.2.jar) 标签或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 everything which 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;amp; instead of &amp; so that the enduser would literally see &amp; 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 there in view.

如果您在处理提交的数据和/或存储在数据库中时对其进行HTML转义,那么它将全部分布在业务代码和/或数据库中。这只是维护问题而且当你在不同的地方做这件事时你会冒险双重逃避或更多(例如&将成为& amp;而不是&以便最终用户真正看到&而不是&在视野中。代码和数据库反过来对XSS不敏感。只有视图是。然后你应该只在视图中转义它。

See also:

#2


6  

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 Prevention备忘单的指南,了解输出编码和输入验证的可能使用情况。

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 ESAPI source code on how the output encoders and input validators are written in a security library.

请查看OWASP ESAPI源代码,了解输出编码器和输入验证器如何在安全库中编写。

#3


0  

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但发送到其他位置。

#1


39  

The normal practice is to HTML-escape any user-controlled data during redisplaying in JSP, not during processing the submitted data in servlet nor during storing in DB. In JSP you can use the JSTL (to install it, just drop jstl-1.2.jar in /WEB-INF/lib) <c:out> tag or fn:escapeXml function for this. E.g.

通常的做法是在JSP中重新显示期间HTML转义任何用户控制的数据,而不是在servlet中处理提交的数据期间或在DB中存储期间。在JSP中,你可以使用JSTL(安装它,只需在/ WEB-INF / lib中删除jstl-1.2.jar) 标签或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 everything which 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;amp; instead of &amp; so that the enduser would literally see &amp; 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 there in view.

如果您在处理提交的数据和/或存储在数据库中时对其进行HTML转义,那么它将全部分布在业务代码和/或数据库中。这只是维护问题而且当你在不同的地方做这件事时你会冒险双重逃避或更多(例如&将成为& amp;而不是&以便最终用户真正看到&而不是&在视野中。代码和数据库反过来对XSS不敏感。只有视图是。然后你应该只在视图中转义它。

See also:

#2


6  

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 Prevention备忘单的指南,了解输出编码和输入验证的可能使用情况。

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 ESAPI source code on how the output encoders and input validators are written in a security library.

请查看OWASP ESAPI源代码,了解输出编码器和输入验证器如何在安全库中编写。

#3


0  

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但发送到其他位置。