Tuesday, February 8, 2011

CSRF Protection Bypass in Ruby on Rails

Posted by michael

There is a vulnerability in Ruby on Rails which could allow an attacker to circumvent the CSRF protection provided. This vulnerability has been assigned the CVE Identifier CVE-2011-0447.

  • Versions Affected: 2.1.0 and above
  • Not affected: Applications which don’t use the built in CSRF protection.
  • Fixed Versions: 3.0.4, 2.3.11

Impact

Certain combinations of browser plugins and HTTP redirects can be used to trick the user’s browser into making cross-domain requests which include arbitrary HTTP headers specified by the attacker. An attacker can utilise this to spoof ajax and API requests and bypass the built in CSRF protection and successfully attack an application. All users running an affected release should upgrade or apply the patches immediately.

Releases

The 3.0.4 and 2.3.11 releases are available at the normal locations.

Upgrade Process

There are two major changes in this fix, the behaviour when CSRF protection fails has changed and the token will now be required for all non-GET requests.

After applying this patch failed CSRF requests will no longer generate HTTP 500 errors, instead the session will be reset. Users can override this behaviour by overriding handle_unverified_request in their own controllers.

Users must still take care that users cannot be auto logged in via non-session data. For example, an application using filters to implement ‘remember me’ functionality must either remove those cookies in their handle_unverified_request handlers or ensure that the remember me code is only executed on GET requests. A custom handler which removes the remember_me cookie would look like:

def handle_unverified_request super # call the default behaviour which resets the session cookies.delete(:remember_me) # remove the auto login cookie so the fraudulent request is rejected. end

There are two steps to ensuring that your application sends the CSRF Token with every ajax request. Providing the token in a meta tag, then ensuring your javascript reads those values and provides them with each request. The first step involves you including the csrf_meta_tag helper somewhere in your application’s layout. Rails 3 applications likely already include this helper, however it has now been backported to the 2.3.x series. An example of its use would be something like this in application.html.erb:

<%= javascript_include_tag :defaults %> <%= csrf_meta_tag %>

In addition to altering the templates, an application’s javascript must be changed to send the token with Ajax requests. Rails 3 applications can just update their rails.js file using rake rails:update, 2.x applications which don’t use the built-in ajax view helpers will need to add a framework-specific snippet to their application.js. Examples of those snippets are available:

Workarounds

There are no feasible workarounds for this vulnerability.

Patches

To aid users who aren’t able to upgrade immediately we have provided patches for the two supported release series. They are in git-am format, 3-0-csrf.patch includes two changesets, the others consist of a single changeset.

Given the severity of the problem we are also providing backported fixes to the 2.2 and 2.1 series. There will be no gem releases for these versions but the stable branches in git will be updated.

Please note that only the 2.3.x and 3.0.x series are supported at present. Users of earlier unsupported releases are advised to upgrade as soon as possible as we cannot guarantee continued security fixes indefinitely.

Credits

Thanks to Felix Gröbert of the Google Security Team for reporting the vulnerability to us and working with us to ensure that the fix didn’t introduce any new issues. Thanks also to the Shopify development team for their assistance in verifying the fix and the upgrade process. The original vulnerability has been reported to vendors by kuza55