XSS
JSF 旨在具有内置的 XSS 预防功能。使用任何 JSF 组件。
<h:outputText value="#{user.name}" />
<h:outputText value="#{user.name}" escape="true" />
<h:inputText value="#{user.name}" />
etc...
请注意,当您在 Facelets 上使用 JSF 2.0 时,您可以像这样在模板文本中使用 EL:
<p>Welcome, #{user.name}</p>
这也将被隐式转义。此处不一定需要<h:outputText>。
仅当您使用 escape="false" 明确取消转义用户控制的输入时:
<h:outputText value="#{user.name}" escape="false" />
那么你就有一个潜在的 XSS 攻击漏洞!
如果您希望将用户控制的输入重新显示为 HTML,其中您希望仅允许特定的 HTML 标签子集,如 <b>、<i>、<u> 等,那么您需要清理通过白名单输入。 HTML解析器Jsoup在这很helpful。
itemLabelEscaped Mojarra 中的错误
较旧的 Mojarra 版本之前 2.2.6 存在以下错误:当通过 <f:selectItems var> 而不是 List<SelectItem> 或 SelectItem[] 作为值提供 List<T> 时,<f:selectItems itemLabel> 错误地呈现未转义的标签(issue 3143)。换句话说,如果您通过List<T> 将用户控制的数据重新显示为项目标签,那么您就有一个潜在的 XSS 漏洞。如果不能选择至少升级到 Mojarra 2.2.6,那么您需要将 itemLabelEscaped 属性显式设置为 true 以防止这种情况发生。
<f:selectItems value="#{bean.entities}" var="entity" itemValue="#{entity}"
itemLabel="#{entity.someUserControlledProperty}" itemLabelEscaped="true" />
CSRF
JSF 2.x 已经在使用服务器端状态保存时在表单中以javax.faces.ViewState 隐藏字段的形式内置了 CSRF 预防。在 JSF 1.x 中,这个值非常弱且太容易预测(它实际上从未打算用作 CSRF 预防)。在 JSF 2.0 中,这已通过使用长而强的自动生成值而不是相当可预测的序列值来改进,从而使其成为一种强大的 CSRF 预防措施。
在 JSF 2.2 中,这甚至通过将其作为 JSF 规范的必需部分以及用于加密客户端状态的可配置 AES 密钥来进一步改进,以防启用客户端状态保存。另见JSF spec issue 869 和Reusing ViewState value in other session (CSRF)。 JSF 2.2 中的新功能是对<protected-views> 的 GET 请求的 CSRF 保护。
只有当您使用<f:view transient="true"> 中的无状态视图,或者应用程序中存在 XSS 攻击漏洞时,您才有潜在的 CSRF 攻击漏洞。
SQL 注入
这不是 JSF 的责任。如何防止这种情况取决于您使用的持久性 API(原始 JDBC、现代 JPA 或良好的 ol'Hibernate),但归根结底,您应该从不将用户控制的输入连接到 SQL 字符串中,例如所以
String sql = "SELECT * FROM user WHERE username = '" + username + "' AND password = md5(" + password + ")";
String jpql = "SELECT u FROM User u WHERE u.username = '" + username + "' AND u.password = md5('" + password + "')";
想象一下如果最终用户选择以下名称会发生什么:
x'; DROP TABLE user; --
您应该始终在适用的情况下使用参数化查询。
String sql = "SELECT * FROM user WHERE username = ? AND password = md5(?)";
String jpql = "SELECT u FROM User u WHERE u.username = ?1 AND u.password = md5(?2)";
在普通 JDBC 中,您需要使用 PreparedStatement 来填充参数值,而在 JPA(和 Hibernate)中,Query 对象也为此提供了设置器。