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:upgrade+, 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:
* prototype-snippet.js - Prototype script which includes the csrf token
in every Ajax request
* jquery-snippet.js - JQuery script which includes the csrf token in
every Ajax request.
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.
* 2-3-csrf.patch - Patch for 2.3 series
* 3-0-csrf.patch - Patch for 3.0 series
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.
* 2-2-csrf.patch - Patch for 2.2 series
* 2-1-csrf.patch - Patch for 2.1 series
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.
--
Cheers,
Koz