Spring Security CSRF Token

In this article of Spring Security tutorial, we will inspect the Spring Security CSRF token or simply known as csrf token. We will look at the different options available with Spring Security CSRF.

Advertisements

Spring Security CSRF Token

CSRF is an attack which tricks customer to submit a malicious request. With the help of CSRF, it let attackers hijacks the identity and let them perform unauthorized work on behalf of the user. For web application, browsers include some critical details which include:

  1. Credentials.
  2. Cookie information.
  3. User session information.
  4. IP Address etc.

So if we already authenticated the user in a site, this makes it really difficult to distinguish between a legitimate and forged request. Spring security provides several features to help handle these kinds of attacks. Before we get into more details, let’s look at how the CSRF attack will happen.

Spring Security CSRF Token
CSRF attack

2. CSRF Prevention

There are multiple options which we can apply to handle this CSRF attack. Here are some of the known options:

  1. Secret Cookie.
  2. HTTPS POST.
  3. Use POST and not GET Method.
  4. URL Rewriting.

All of them can add some additional checks but they don’t prevent these types of attacks and we may need some additional steps/ checks to handle it.

3. Synchronizer Token Pattern

Spring Security CSRF Token provides protection against these attacks using the synchronizer token pattern. Let’s see how this pattern works to help us secure the HTTP request.

  1. Each HTTP request requires, besides our session cookie, a secure random generated value called a CSRF token.
  2. Server store this token on the server end and also passes it to the client.
  3. This CSRF token must be present in the HTTP request coming out of the customer.
  4. When an HTTP request is submitted, the server must look up the expected CSRF token and compare it against the actual CSRF token in the HTTP request.
  5. If the token values not matching on both sides, the request is treated as potential forged request and will be rejected.
  6. We do not include spring security CSRF token in the GET request as it can easily leak this.

This additional CSRF token should be in a part of the HTTP request that is not automatically included by the browser.

The CSRF token is not part of the cookie since the browser automatically included cookies in the HTTP request. This adds another layer of security, as it forced us to send the token in the HTTP request by adding it to the payload.

Let’s see how this process work to help us avoid the attack.

Spring Security CSRF Token
Spring Security CSRF Token

This CSRF token must be submitted to the server on every HTTP request that changes state (PATCH, POST, PUT, and DELETE except GET). If you are interested, look at the CsrfFilter class to understand how it generates and validates the token.

With the CSRF token, this is how the request will look like:

POST /refund HTTP/1.1
Host: javadevjournal.com
Cookie: JSESSIONID=randomid;Domain=javadevjournal.com; Secure; HttpOnly
Content-Type: application/x-www-form-urlencoded

amount=340.00&_csrf=4bfd1575-3ad1-4d21-96c7-4ef2d9f86721

With each POST request, we are adding _csrf parameter with a random value and it will verify this value with the token stored at the server side. It will not be easy for the malicious website to guess the correct value for the _csrf parameter.

An emerging way to protect against CSRF Attacks is to specify the SameSite Attribute on cookies. A server can specify the SameSite attribute when setting a cookie to show that the cookie should not be sent when coming from external sites.

3.1 Enabling CSRF Token in Spring Security

Spring security provides OOTB support for the CSRF token and it’s enabled by default. We don’t need any specific steps to enable this feature, however you can disable this feature by csrf().disable() in your Spring security config class.

@Override
protected void configure(HttpSecurity http) throws Exception {
  http.csrf().disable();
}

With default setup, if you look at the source code of the page, you will see the _csrf parameter being added automatically to the form by Spring security. Here is the HTML source for the registration page of our Spring security tutorial.

<form action="/register" method="post">
  <input type="hidden" name="_csrf" value="6c5e7122-b45a-4255-99a4-ec162b156ed6" />

  <div class="row">
    <!-- /.col -->
    <div class="col-4">
      <button type="submit" class="btn btn-primary btn-block">Register</button>
    </div>
    <!-- /.col -->
  </div>
</form>

3.2. When to use CSRF protection

We should activate the Spring security CSRF for the following use cases:

  1. If a normal user triggers the request.
  2. In case it’s processed by browser.

We can disable this in case a client other than browser or user start and process the request.

Advertisements
Advertisements

4. Ajax and JSON Request

In case we are using JSON or an Ajax request, it’s not possible to include the CSRF token as a request parameter. Spring security provides the following options to send the token.

4.1. Meta Tag

One option is to include the token as meta tag.The HTML might look something like this:

<head>
    <meta name="_csrf" content="4bfd1575-3ad1-4d21-76yh-5ygfuyd9f86721"/>
    <meta name="_csrf_header" content="X-CSRF-TOKEN"/>
    <!-- ... -->
</head>

4.2. AJAX send CSRF Token

For JQuery or similar framework, we can use something like:

$(function () {
    var token = $("meta[name='_csrf']").attr("content");
    var header = $("meta[name='_csrf_header']").attr("content");
    $(document).ajaxSend(function(e, xhr, options) {
        xhr.setRequestHeader(header, token);
    });
});

4.3. Automatic CSRF Token Inclusion

With Spring’s form tag library, Thymleaf, or any other view technology that integrates with RequestDataValueProcessor, it will automatically include the actual CSRF token for unsafe HTTP method. In case you are not using these tag libraries, we can easily include the token with the csrfInput tag:

<form method="post" action="register">
    <sec:csrfInput />
</form>

There are certain use cases where you won’t be able to use the supported tag libraries or can’t include the csrfInput tag, remember this CSRF token is exposed as an HttpServletRequest attribute named _csrf. We can include the token with a similar approach:

<form action="/register" method="post">
    <input type="hidden" name="${_csrf.parameterName}"  value="${_csrf.token}"/>
</form>

5. CSRF and Stateless Applications

If a user does not need to perform any actions in the web browser for a request, they are likely still vulnerable to CSRF attacks. This is really important in case we are using session cookie authentication. For this kind of authentication, we should enable Spring security CSRF token feature.

If we are using JWT based token mechanism, we don’t need CSRF protection and we must disable.

We can Custom CsrfTokenRepository approach to add CSRF protection for the stateless applications.

5.1. Custom CsrfTokenRepository

Spring security by default stores the expected CSRF token in the HttpSession using HttpSessionCsrfTokenRepository. For stateless application, we can configure a custom CsrfTokenRepository to persist the CsrfToken in a cookie. We can use CookieCsrfTokenRepository write to a cookie named XSRF-TOKEN and read it from a header named X-XSRF-TOKEN or the HTTP parameter _csrf. You can configure custom token repository as:

@EnableWebSecurity
public class WebSecurityConfig extends
WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) {
        http
            .csrf(csrf - >
                csrf
                .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
            );
    }
}

6. Caveats

We should know some caveats while using the CSRF in Spring Security.

6.1. Session Timeout

As we know CSRF token are stored in the HTTPSession so as soon as session is expired, the AcessDeniedHandler will get an InvalidCsrfTokenException. With this, customer will get access denied message or page. Here are some of the option to mitigate this issue:

  1. Use Ajax call to request a CSRF token on form submission.This will get the update token and will submit it as part of the request payload.
  2. We can also build an Ajax based feature to check the session and inform the customer to refresh it before submitting the form.
  3. We can also store CSRF token in a cookie (Please be aware that it poses certain security issue)

6.2. Logging In

We should protect the login form against CSRF attacks for any forged login request. Spring security provides OOTB support for login.

6.3. Logging out

If the CSRF feature is enable in Spring security, it adds a security check by enabling LogoutFilter to only process HTTP POST. This will ensure that only valid user with a valid token is allowed to send logout request.

it’s not recommended to enable the logout using GET method as this exposes your user for exploit.

Sumarry

In this article, we explored the various features of CSRF protection with Spring security. We saw that this security feature is active by default in Spring security. We also saw different options to customize the feature in Spring Security. As always, the source code for this series in available in our GitHub Repository.

Advertisements