我有一个基于JSF的Web应用程序,MySQL作为DB。我已经在我的应用程序中实现了代码以防止CSRF。
既然我的底层框架是JSF,我想我不必处理XSS攻击,因为它已由UIComponent
处理。我没有在任何视图页面中使用任何JavaScript。即使我使用了,我真的需要实现代码来防止XSS攻击吗?
对于DB,我们在所有数据库交互中使用预准备语句和存储过程。
是否还需要处理其他任何事情以防止这3种常见攻击? 我已浏览过OWASP网站及其cheat sheets。
我是否需要处理任何其他潜在的攻击媒介?
答案 0 :(得分:105)
JSF旨在内置XSS预防。您可以安全地重新显示所有用户控制的输入(请求标头(包括Cookie!),请求参数(也包括保存在DB中的参数!)和请求正文(上传的文本文件等))任何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"
明确 unescaping 用户控制的输入时仅:
<h:outputText value="#{user.name}" escape="false" />
然后你有一个潜在的XSS攻击漏洞!
如果您想将用户控制的输入重新显示为HTML,而您希望仅允许<b>
,<i>
,<u>
等HTML标记的特定子集,那么你需要通过白名单来清理输入。 HTML解析器Jsoup非常helpful。
itemLabelEscaped
错误&lt; 2.2.6 2.2.6之前的较早的Mojarra版本有错误,<f:selectItems itemLabel>
在List<T>
通过<f:selectItems var>
而不是{{1}提供List<SelectItem>
时错误地将标签呈现为未转义的错误}或SelectItem[]
作为值(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" />
当使用服务器端状态保存时,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攻击漏洞。
这不是JSF的责任。如何防止这种情况取决于您正在使用的持久性API(原始JDBC,现代JPA或良好的'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
对象也为此提供了设置器。
答案 1 :(得分:8)
我没有在任何视图页面中使用任何JavaScript。即使我使用了,我真的需要实现代码来绕过XSS Attack。
即使您不在页面中使用JavaScript,也容易受到XSS攻击。当您合并攻击者控制的内容而未正确编码时,就会发生XSS。
您可以随时执行
之类的操作response.write("<b>" + x + "</b>")
如果攻击者可能导致x
包含包含JavaScript的HTML,则您很容易受到XSS攻击。
解决方案通常不是编写大量代码。通常,解决方案是将$x
和攻击者控制的任何其他值编码,然后将其包含在您生成的HTML中。
response.write("<b>" + escapePlainTextToHtml(x) + "</b>")
过滤或消毒输入有助于提供额外的保护层。
<shameless-plug>
您还可以使用自动编码输出的模板语言来防止XSS。
Closure Template是Java的一个选择。
上下文自动转换通过扩充Closure模板来根据其出现的上下文对每个动态值进行正确编码,从而抵御攻击者控制的值中的XSS漏洞。
修改
由于您使用的是JSF,因此您应该阅读XSS mitigation in JSF:
转义输出文字
<h:outputText/>
和<h:outputLabel/>
默认情况下将escape属性设置为True。通过使用此标记显示输出,您可以缓解大部分XSS漏洞。SeamTextParser和
<s:formattedText/>
如果您想允许用户使用一些基本的html标签来自定义他们的输入,JBoss Seam提供了一个
<s:formattedText/>
标签,允许用户指定一些基本的html标签和样式。
答案 2 :(得分:0)
在将<h:outputText escape="false">
与未转义的值一起使用(例如来自html文本编辑器)时,您容易受到讨厌的XSS攻击。在这种情况下,我使用的是JSF转换器,该转换器使用Jsoup从文本中删除javascript,而HTML保持完整。 Converter也可以用于清理用户输入。您可以像这样使用它:
<h:outputText value="{bean.value}" escape="false" converter="htmlSanitizingConverter"/>
转换器本身:
/**
* Prevents from XSS attack if output text is not escaped.
*/
@FacesConverter("htmlSanitizingConverter")
public class HtmlSanitizingConverter implements Converter {
private static final Whitelist JSOUP_WHITELIST = Whitelist.relaxed()
.preserveRelativeLinks(true)
.addAttributes(":all","style");
/*
Optionally - add support for hyperlinks and base64 encoded images.
.addTags("img")
.addAttributes("img", "height", "src", "width")
.addAttributes("a", "href")
.addProtocols("img", "src", "http", "https", "data");
*/
@Override
public Object getAsObject(FacesContext context, UIComponent component, String submittedValue) {
return (submittedValue != null) ? Jsoup.clean(submittedValue, JSOUP_WHITELIST) : null;
}
@Override
public String getAsString(FacesContext context, UIComponent component, Object value) {
return (value != null) ? Jsoup.clean(value.toString(), JSOUP_WHITELIST) : "";
}
}
注意:
当您将JSF与PrimeFaces结合使用时,请注意,<p:textEditor>
-older versions(6.2之前的版本)默认情况下不会清除用户输入。