DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports Events Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones AWS Cloud
by AWS Developer Relations
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones
AWS Cloud
by AWS Developer Relations
  1. DZone
  2. Coding
  3. Java
  4. A Java Implementation of CSRF Mitigation Using 'Double Submit Cookie' Pattern

A Java Implementation of CSRF Mitigation Using 'Double Submit Cookie' Pattern

A tutorial to implement the double submit cookie pattern used to mitigate cross-site request forgery attacks using Java filters.

Adrian CITU user avatar by
Adrian CITU
·
Jan. 18, 17 · Tutorial
Like (10)
Save
Tweet
Share
50.55K Views

Join the DZone community and get the full member experience.

Join For Free

Goal of This Article

The goal of this article is to present an implementation of the "double submit cookie" pattern used to mitigate Cross Site Request Forgery (CSRF) attacks. The proposed implementation is a Java filter plus a few auxiliary classes and it is (obviously) suitable for projects using the Java language as backend technology.

Definition of CSRF and Possible Mitigations

In the case of a CSRF attack, the browser is tricked into making unauthorized requests on the victim’s behalf, without the victim’s knowledge. The general attack scenario contains the following steps:

  1. The victim connects to the vulnerable web site, so it has a real, authenticated session.
  2. The hacker forces the victim (usually using a spam/phishing email) to navigate to another (evil) website containing the CSRF attack.
  3. When the victim's browser execute the (evil) website page, the browser will execute a (fraudulent) request to the vulnerable website using the user authenticated session. The user is not aware at all of the fact that navigating on the (evil) website will trigger an action on the vulnerable web-site.

In order to mitigate the CSRF attacks the following techniques can be used:

  • Verifying the same origin with standard headers — This technique consists in determining the origin the request is coming from (source origin) and determining the origin the request is going to (target origin).
  • Synchronizer token pattern – An anti-CSRF token is created and stored in the user session and in a hidden field on subsequent form submits. At every submit, the server checks the token from the session matches the one submitted from the form. Tomcat 6+ implements this pattern (for more info, please see CSRF Protection Filter), and the OWASP CSRFGuard project offers another implementation.
  • Challenge/response pattern – The solution consists in forcing the user to enter a value known only to him in order to complete the action.
  • Encrypted token pattern — When a user authenticates to a site, the site should generate a unique token comprised of the user's ID, a timestamp value and a nonce, using a unique key available only on the server. The token is returned to the client and embedded into a hidden field. When the form is posted on server, the server decrypts the token and verifies that the use ID retrieved from the token matches the one from the session.
  • Double-cookie submit pattern – This will be defined in the next paragraph.

For deeper explanations I strongly recommend  to read chapter 5 of Iron-Clad Java: Building Secure Applications book and/or the OWASP Cross-Site Request Forgery (CSRF) Prevention Cheat Sheet.

Definition of "Double Submit Cookie" Pattern

When a user authenticates to a site, the site should generate a (cryptographically strong) pseudo-random value and set it as a cookie on the user’s machine separate from the session ID. The server does not have to save this value in any way, that's why this pattern is also called Stateless CSRF Defense.

The site then requires that every transaction request include this random value as a hidden form value (or other request parameter). A cross origin attacker cannot read any data sent from the server or modify cookie values, per the same-origin policy.

In the case of this mitigation technique the job of the client is very simple, just retrieve the CSRF cookie from the response and add it into a special header to all the requests:

  csrfclient
Client workflow

The job of the server is a little more complex, create the CSRF cookie and for each request asking for a protected resource, check that the CSRF cookie and the CSRF header of the request are matching:

csrfserver
Server workflow

Note that some JavaScript frameworks like AngularJS implements the client worflow out of the box, see Cross Site Request Forgery (XSRF) Protection.

Java Implementation of "Double Submit Cookie" Pattern

The proposed implementation is on the form of a (Java) Servlet filter and can be found here: GenericCSRFFilter GitHub.

In order to use the filter, you must define it into you web.xml file:

<filter>
   <filter-name>CSRFFilter</filter-name>
   <filter-class>com.github.adriancitu.csrf.GenericCSRFStatelessFilter</filter-class>
<filter>

<filter-mapping>
   <filter-name>CSRFFilter</filter-name>
   <url-pattern>/*</url-pattern>
</filter-mapping>

The filter can have two optional initialization parameters: csrfCookieName, which represents the name of the cookie that will store the CSRF token, and csrfHeaderName, which represents the name of the HTTP header that will also contain the CSRF token.

The default values for these parameters are "XSRF-TOKEN" for the csrfCookieName and "X-XSRF-TOKEN" for the csrhHeaderName, both of them being the default values that AngularJS is expecting to have in order to implement the CSRF protection.

By default the filter has the following features:

  • Works with AngularJS.
  • The CSRF token will be a random UUID.
  • All the resources that are NOT accessed through a GET request method will be CSRF protected.
  • The CSRF cookie is replaced after each non GET request method.

How It's Working Under the Hood

The most of the functionality is in the GenericCSRFStatelessFilter#doFilter method, here is the sequence diagram that explains what's happening in this method:

doFilter method sequence diagram
doFilter method sequence diagram

The doFilter method is executed on each HTTP request:

  1. The filter creates an instance of ExecutionContext class, this class is a simple POJO containing the initial HTTP request, the HTTP response, the CSRF cookies (if more than one cookie with the csrfCookieName is present) and implementation of the ResourceCheckerHook, TokenBuilderHook, and ResponseBuilderHook. (See the next section for the meaning of this classes).
  2. The filter check the status of the HTTP resource, that status can be: MUST_NOT_BE_PROTECTED, MUST_BE_PROTECTED_BUT_NO_COOKIE_ATTACHED, MUST_BE_PROTECTED_AND_COOKIE_ATTACHED (see ResourceStatus enum) using an instance of ResourceCheckerHook.
  3. If the resource status is ResourceStatus#MUST_NOT_BE_PROTECTEDResourceStatus#MUST_BE_PROTECTED_BUT_NO_COOKIE_ATTACHED then the filter creates a CSRF cookie having as token the token generated by an instance of TokenBuilderHook.
  4. If the resource status ResourceStatus#MUST_BE_PROTECTED_AND_COOKIE_ATTACHED then compute the CSRFStatus of the resource and then use an instance of ResponseBuilderHook to return the response to the client.

How to Extend the Default Behavior

It is possible to extend or overwrite the default behavior by implementing the hooks interfaces. All the hooks implementations must be thread safe.

  1. The ResourceCheckerHook is used to check the status of a requested resource. The default implementation is DefaultResourceCheckerHookImpl and it will return ResourceStatus#MUST_NOT_BE_PROTECTED for any HTTP GET method, for all the other request types, it will return {@link ResourceStatus#MUST_BE_PROTECTED_BUT_NO_COOKIE_ATTACHED if any CSRF cookie is present in the query or ResourceStatus#MUST_BE_PROTECTED_BUT_NO_COOKIE_ATTACHED otherwise. The interface signature is the following one:
    public interface ResourceCheckerHook extends Closeable {
        ResourceStatus checkResourceStatus(ExecutionContext executionContext);
    }  
  2. The TokenBuilderHook hook is used to generate the token that will be used to create the CSRF cookie. The default implementation  is DefaultTokenBuilderHookImpl and it uses a call to UUID.randomUUID to fetch a token. The interface signature is the following one:
    public interface TokenBuilderHook extends Closeable {
        String buildToken(ExecutionContext executionContext);
    }
  3. The ResponseBuilderHook is used to generate the response to the client depending of the CSRFStatus of the resource. The default implementation is DefaultResponseBuilderHookImpl and it throws a SecurityException if the CSRF status is CSRFStatus#COOKIE_NOT_PRESENT, CSRFStatus#HEADER_TOKEN_NOT_PRESENT, or CSRFStatus#COOKIE_TOKEN_AND_HEADER_TOKEN_MISMATCH. If the CSRF status is CSRFStatus#COOKIE_TOKEN_AND_HEADER_TOKEN_MATCH, then the old CSRF cookies are deleted and a new CSRF cookie is created. The interface signature is the following one:
    public interface ResponseBuilderHook extends Closeable {
        ServletResponse buildResponse(ExecutionContext executionContext,
                                      CSRFStatus status);
    }

The hooks are instantiated inside the GenericCSRFStatelessFilter#init method using the ServiceLoader Java 6 loading facility. So if you want to use your implementation of one of the hooks then you have to create a META-INF/services directory that contains a text file whose name matches the fully-qualified interface class name of the hook that you want to replace.

Here is the sequence diagram representing the hooks initializations:

initmethod

Implementation Java (programming language) Requests

Published at DZone with permission of Adrian CITU, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • Comparing Map.of() and New HashMap() in Java
  • DevOps for Developers: Continuous Integration, GitHub Actions, and Sonar Cloud
  • Solving the Kubernetes Security Puzzle
  • Top 10 Best Practices for Web Application Testing

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com
  • +1 (919) 678-0300

Let's be friends: