Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does Rails CSRF protection work?

Tags:

Rails raises an InvalidAuthenticityToken when the CSRF token doesn't match. But, from reading the source, I can't figure out how this actually happens. I start by acking the tree for that class:

$ ack --ignore-dir=test InvalidAuthenticityToken  actionpack/lib/action_controller/metal/request_forgery_protection.rb 4:  class InvalidAuthenticityToken < ActionControllerError #:nodoc: 17:  # which will check the token and raise an ActionController::InvalidAuthenticityToken  actionpack/lib/action_dispatch/middleware/show_exceptions.rb 22:      'ActionController::InvalidAuthenticityToken' => :unprocessable_entity 

Only two hits, ignoring the comment. The first one is the class definition:

class InvalidAuthenticityToken < ActionControllerError #:nodoc: end 

The second one is translating the exception into an HTTP status code. CSRF protection gets enabled by calling protect_from_forgery in the controller, so let's look at that:

def protect_from_forgery(options = {})   self.request_forgery_protection_token ||= :authenticity_token   before_filter :verify_authenticity_token, options end 

It adds a filter:

def verify_authenticity_token   verified_request? || handle_unverified_request end 

Which calls this when verification fails:

def handle_unverified_request   reset_session end 

So how is InvalidAuthenticityToken actually raised?

like image 654
David Phillips Avatar asked Feb 15 '11 05:02

David Phillips


People also ask

How does rails generate CSRF token?

Rails CSRF TokenThe server generates these tokens, links them to the user session, and stores them in the database. This token is then injected into any form presented to the client as a hidden field. When the client correctly submits the form for validation, it passes the token back to the server.

How does the authenticity token work in Rails?

When the user submits the form, Rails looks for the authenticity_token , compares it to the one stored in the session, and if they match the request is allowed to continue. Since the authenticity token is stored in the session, the client cannot know its value.

How does CSRF authentication work?

A CSRF token is a secure random token (e.g., synchronizer token or challenge token) that is used to prevent CSRF attacks. The token needs to be unique per user session and should be of large random value to make it difficult to guess. A CSRF secure application assigns a unique CSRF token for every user session.

How does REST API protect CSRF?

Enable CSRF Protection With REST API If our project requires CSRF protection, we can send the CSRF token with a cookie by using CookieCsrfTokenRepository in a custom WebSecurityConfigurerAdapter. After restarting the app, our requests receive HTTP errors, which means that CSRF protection is enabled.


1 Answers

The behavior was changed fairly recently but the documentation has yet to be updated. The new approach being used is to presume the session has been hijacked, and therefore to clear the session. Assuming your session contains the all-important authentication information for this request (like the fact you're logged in as alice) and your controller assures the user is authenticated for this action, your request will be redirected to a login page (or however you choose to handle a non logged-in user). However, for requests which are not authenticated, like a sign-up form, the request would go through using an empty session.

It seems this commit also goes on to close a CSRF vulnerability, but I didn't read into the details of that.

To obtain the old behavior, you would simply define this method:

def handle_unverified_request   raise(ActionController::InvalidAuthenticityToken) end 

You can read more about CSRF and other Rails security issues at the Ruby on Rails Security Guide.

like image 105
wuputah Avatar answered Sep 30 '22 01:09

wuputah