如何在JSF-Spring集成应用中开启CSRF保护

Sam*_*Sam 1 java jsf spring spring-security csrf-protection

我有一个 JSF-Spring 集成应用程序。此应用程序中还集成了 Spring 安全性。这些是我的应用程序中的版本:

  • JSF 2.2
  • 春季 4.0.3.RELEASE
  • Spring 安全 3.2.4.RELEASE

根据JSF 文档,JSF2.x [甚至旧版本] 中的所有 POST 请求都将受到 CSRF 保护。但是,我能够通过 CSRF 攻击来渗透我的应用程序。

我只尝试了一个不同的 JSF2.2 [没有 Spring] 示例应用程序,在这种情况下,我可以看到这个示例应用程序受 CSRF 保护。

所以我的理解是,JSF/Spring/Spring 安全组合在我的原始应用程序中出现了问题。不幸的是,日志文件中没有帮助信息。

我可以尝试使用Spring Security CSRF 保护。在那种情况下,挑战是我需要在所有 POST 情况下编辑代码。

我希望启用 JSF CSRF 保护以避免此代码更改。有什么建议吗?

我正在用Pinata进行测试。

Tec*_*ter 5

使用 Spring 4.3.7 和 Spring Security 4.2.2 进行测试。

您需要为form应用程序中的每一个添加一个 CSRF 令牌。任何 PATCH、POST、PUT 和 DELETE都将受到 Spring 安全性的保护(对于基本动词)。为了避免在每个表单中手动插入隐藏的输入,您可以在提供的表单之上创建一个 FormRenderer :

import com.sun.faces.renderkit.html_basic.FormRenderer;

import javax.el.ELContext;
import javax.el.ExpressionFactory;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import java.io.IOException;

public class FormWithCSRFRenderer extends FormRenderer {

    @Override
    public void encodeEnd(FacesContext context, UIComponent component) throws IOException {
        log.debug("FormWithCSRFRenderer - Adding CSRF Token to form element");
        ELContext elContext = context.getELContext();
        ExpressionFactory expFactory = context.getApplication().getExpressionFactory();

        ResponseWriter writer = context.getResponseWriter();
        writer.startElement("input", component);
        writer.writeAttribute("type", "hidden", null);
        writer.writeAttribute("name", expFactory.createValueExpression(elContext, "${_csrf.parameterName}", String.class).getValue(elContext), null);
        writer.writeAttribute("value", expFactory.createValueExpression(elContext, "${_csrf.token}", String.class).getValue(elContext), null);
        writer.endElement("input");
        writer.write("\n");
        super.encodeEnd(context, component);
    }
}
Run Code Online (Sandbox Code Playgroud)

然后通过将其设置为将其注册以覆盖 FormRenderer faces-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<faces-config xmlns="http://xmlns.jcp.org/xml/ns/javaee"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_2.xsd"
              version="2.2">
    <render-kit>
        <renderer>
            <component-family>javax.faces.Form</component-family>
            <renderer-type>javax.faces.Form</renderer-type>
            <renderer-class>com.acme.FormWithCSRFRenderer</renderer-class>
        </renderer>
    </render-kit>
</faces-config>
Run Code Online (Sandbox Code Playgroud)

也不要忘记在你的 spring 上下文中启用 CSRF :

<security:http auto-config="true" entry-point-ref="preAuthenticatedProcessingFilterEntryPoint"
               use-expressions="true">
    <security:csrf/>
    <security:access-denied-handler error-page="/exception/accessDenied.xhtml"/>

    <security:intercept-url pattern="/**" access="hasAnyRole('ROLE_ADMINISTRATOR','ROLE_GUEST')"/>
    <security:intercept-url pattern="/exception/accessDenied.xhtml" access="permitAll"/>
</security:http>
Run Code Online (Sandbox Code Playgroud)

对于您的 AJAX 调用,您还需要将此令牌添加到任何受保护的 HTTP 动词的数据中。您可以直接从 DOM 中检索令牌。