Four weeks ago, we blogged about the issue with Rails' built-in anti-CSRF mechanism, protect_from_forgery, where we calculated that over 50,000 Ruby developers were impacted by Cross-site Request Forgery (CSRF) attacks.
The default configuration for Rails'
ActionController::Base does not automatically include the anti-CSRF mechanism,
protect_from_forgery. There is an open PR in Rails made in December 2016 to change this. Details about the cause of the issue, the vulnerability, and the fix can be read in a previous blog post about the same CSRF issue, in the
Rails_admin gem, here.
There have been many lessons learned along this journey including starting to understand just how many vulnerabilities, backdoors and signs of malware there are in the open-source ecosystem and how hard some are to detect at scale. I am pretty sure Mark Curphey's keynote at Hack in the Box in Singapore will now be called Hiding in Plain Sight.
One lesson we learned is that given the size of the vulnerability pool (see above) and the responsiveness of the majority of open-source maintainers is that we fundamentally need to re-think our approach to disclosure in open-source. We have run several tests like this and all show similar results.
CSRF Disclosure Summary
We contacted 50 maintainers of affected Rails engines to tell them that they had the issue and suggesting a simple fix. A summary of the state of disclosures can be seen in the chart below.
Of the 50 contacts, 16 promptly resolved the issue. Well done you. 11 others acknowledged the mail but have not yet released a fix 30 days later and one fixed it in silence. The other 23 have not responded to the initial contact or a subsequent reminder.
For most cases, the fix was as simple as adding the
protect_from_forgery with: :exception line right after the Controller which inherits from
ActionController::Base. For more information, the summary of the affected Rails projects can be viewed at this link.
A fix to enable the anti-CSRF mechanism is simple and usually only requires an additional line in the affected areas. An example fix for most Rails Application would be as follows:
class ApplicationController < ActionController::Base + protect_from_forgery with: :exception +
For APIs, it would be as follows:
class ApplicationController < ActionController::Base + protect_from_forgery with: :null_session +
This type of CSRF vulnerabilities in Rails Applications can be easily prevented and we think CSRF Protection should be on by default.
Disclosure in open-source projects is hard. In our experience the majority of projects when notified neither acknowledge or respond to disclosures and most simply do fix issues issues when reported.