December 15th, 2011
(written by lawrence krubner, however indented passages are often quotes). You can contact lawrence at: email@example.com
My personal understanding of Rails up until an hour ago was that a CSRF violation would raise an exception. This would practically never get seen by a legitimate user operation, so few people are aware of that, but I had seen it a time or two when security auditing BCC. (Some of my geeky friends had, back in the day, exploited BCC with a CSRF and helpfully told me how to fix it. Naturally, after fixing it I verified that the site worked as expected with the fix.)
So if the CSRF protection was somehow eating sessions, I would expect to see that exception getting logged and emailed to me by Airbrake (formerly Hoptoad — it emails you when an exception happens in production, highly recommended). That wasn’t happening.
Then I decided to dig into the Rails source. Whereupon I learned that Rails 2.3.11 changed the behavior of CSRF protection: instead of throwing exceptions, it would silently just clear the session and re-run the request. For most sensitive operations (e.g. those which require a signed in user), this would force a signout and then any potentially damaging operation would be averted.
Here’s the relevant code in Rails 2.3.11:
verified_request? || handle_unverified_request
Versus the relevant code in Rails 2.3.10 (sidenote: you can see all of this easily in Github because Rails is diligent about tagging releases, a practice you should certainly follow in your own development):
verified_request? || raise(ActionController::InvalidAuthenticityToken)
And, sure enough, checking Subversion showed that I upgraded the version of Rails I was using in January of this year in response to this security advisory. I read that, made the required modifications to my application, tested, and had no problems.