Jersey and Cross-Site Request Forgery (CSRF)

September 14th, 2011 by Martin Leave a reply »

About two weeks back we released Jersey 1.9. See Jakub’s blog for more info on what’s new. One thing Jakub didn’t mention is that Jersey 1.9 also includes a new server side filter for Cross Site Request Forgery prevention. I won’t go into the details on what CSRF is – please refer to the OWASP CSRF page for that. Unfortunately, the generally recommended prevention is to generate per-request or per-session tokens on the server side, which client then has to include in its subsequent requests. This is quite easy to implement and there are servlet filters for doing that, however it does require a session state to be maintained and thus is not very RESTful. I was trying to implement something that would not require a session. After some searching I found the following two papers which both suggest there is a solution which works, and is not based on sessions:

The main idea is to check the presence of a custom header (agreed-upon between the server and a client – e.g. X-CSRF or X-Requested-By) in all state-changing requests coming from the client. The value of the header does not really matter. It works, because the browser would not send custom headers unless the web page makes a request using XMLHttpRequest, which only allows requests to the same site.

So, in Jersey 1.9 we added a server-side filter which does exactly that. You can find it here: server-side CsrfProtectionFilter.java

And, to make it easy to build clients, a corresponding client filter (that attaches the custom header to all potentially state-changing requests) is there as well: client-side CsrfProtectionFilter.

This can be further extended based on the feedback – we may add a check for the Referrer header and eventually even implement the session-based solution as an available configuration option. Just let us know, if you have an opinion.

9 comments

  1. Vijay says:

    Will this XmlHttprequest solution work if it is an Android mobile client making calls via Apache HttpClient with the X-CSRF header ?

  2. Justin says:

    In the first reference it states:

    These technologies can set custom HTTP headers, but
    have security policies built in to prevent web sites from sending requests to each other
    unless specifically allowed by policy.

    The key thing here is ‘web sites’, what if the you are trying to protect your REST endpoints from CSRF attacks that originate from a browser that you have established trust with. You can’t drop the request to the end point since it comes the same machine!

    RESTful services if they remain stateless (which they must to be called RESTful) are forced to trust the browser. If the browser is comprimised then there is nothing that can protect the services.

    I have yet to see an argument that can convince me that you could build a html + javascript + REST application that is secure.

    • Manikanta says:

      Hi Justin,

      When the browser is compromised (or, browser vendor willingly or unknowingly didn’t implemented some security measures correctly), the said problem could come not just to the HTML + JS + REST combination, either CSRF approach, but to every thing we do using that browser. Meaning, if cross domain validation failed when Ajax request was made to different domain instead of origin domain, that is an severe issue. Correct me if not.

  3. andrew says:

    Stupid question, but how to register thie filter?

  4. andrew says:

    sorry for previous question, I assked too fast, I found solution

  5. Ward says:

    It looks like I misunderstood the previous article, sorry about that.

  6. O B says:

    Hi,
    Can you provide an example of how to write a client that login to a site with csrf?
    I can’t find any.

    Thanks,

Leave a Reply