JSF中的CSRF,XSS和SQL注入攻击防范

时间:2011-10-11 06:30:16

标签: jsf xss sql-injection csrf owasp

我有一个基于JSF的Web应用程序,MySQL作为DB。我已经在我的应用程序中实现了代码以防止CSRF。

既然我的底层框架是JSF,我想我不必处理XSS攻击,因为它已由UIComponent处理。我没有在任何视图页面中使用任何JavaScript。即使我使用了,我真的需要实现代码来防止XSS攻击吗?

对于DB,我们在所有数据库交互中使用预准备语句和存储过程。

是否还需要处理其他任何事情以防止这3种常见攻击? 我已浏览过OWASP网站及其cheat sheets

我是否需要处理任何其他潜在的攻击媒介?

3 个答案:

答案 0 :(得分:105)

XSS

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

Mojarra中的

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" />

CSRF

当使用服务器端状态保存时,JSF 2.x已经在表单javax.faces.ViewState隐藏字段的内容中构建了CSRF预防。在JSF 1.x中,这个值非常弱并且太容易预测(实际上它从未打算用作CSRF预防)。在JSF 2.0中,通过使用长而强的自动生成值而不是可预测的序列值来改进这一点,从而使其成为强大的CSRF预防。

在JSF 2.2中,如果启用了客户端端状态保存,则可以通过将其作为JSF规范的必需部分以及用于加密客户端状态的可配置AES密钥来进一步改进。另请参阅JSF spec issue 869Reusing ViewState value in other session (CSRF)。 JSF 2.2中的新功能是<protected-views>对GET请求的CSRF保护。

只有当您使用<f:view transient="true">中的无状态视图,或者应用程序中存在某个XSS攻击漏洞时,您才会遇到潜在的CSRF攻击漏洞。


SQL注入

这不是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漏洞。

     

SeamT​​extParser和<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之前的版本)默认情况下不会清除用户输入。