There’s been a lot of commotion lately about the critical vulnerability in Rails (>= Rails 2). And with good reason. For technical details, you can see any number of write-ups, including the post on the Rails-core mailing list from Aaron Patterson, this post on Rapid7, and this discussion on Hacker News. There are also posts on the EngineYard blog and Heroku blog.
In this article though, I’d like to 1) boil the issue down to its most basic principle, and 2) outline your options for fixing.
At the root of this, is the fact that Rails has the ability to accept XML in the parameters and automatically marshalls objects from the XML parameter, including YAML and symbol keys, which can be used to exploit vulnerabilities in ActiveRecord, Arel, and a bunch of other gems. In the worst case scenario, these exploits can be used to gain access to the server shell, at which point a hacker could do pretty much anything they wanted to a server. Because of this, absolutely ALL rails apps you’ve ever built that are still live, and rails version 2 or later, NEED TO BE UPDATED.
If you have a vulnerable application anywhere, on any port it will be found and compromised. This is a spray-and-pray vulnerability. It costs attackers nothing to try, attempts don't crash servers, and so people will try everywhere. If you lose an application in your data center / hosting environment, that's the ballgame. It doesn't matter that the app you lost was the testing instance of a status dashboard with no real data in it, because the exploit coughs up shell access on that server. If there is one thing every black-hat attacker in the world is truly gifted at, it is pivoting from shell access on one server to shell access on every goddam server. Please make sure you didn't just patch the app servers you know/care about. THEY ALL NEED TO BE PATCHED OR RETIRED.
The way to fix this is to either apply one of the patches located here manually to each Rails installation.
Or, to just upgrade to the latest applicable patch:
2.3.x => 2.3.15 3.0.x => 3.0.19 3.1.x => 3.1.10 3.2.x => 3.2.11
For the older Rails 2 apps, if updating Rails causes too many issues or a client doesn’t want to invest the time, the simplest way to fix this is to just turn off XML parameter parsing (assuming nothing in the app and none of the app’s gems use it). This can be done by putting one of the following in an initializer (e.g. config/initializers/disable_xml_parsing.rb) in the app itself.
If you don’t want to completely turn off XML parameter parsing, you could also just turn off YAML and symbol marshalling within the XML parser specifically:
To test to see if this worked, run this from the terminal (thanks to vinhboy on Hacker News for this snippet):
curl -i -H "Content-Type: application/xml" -X POST -d '<id type="yaml">--- !ruby/object:ActionController::Base bar: 1</id>' http://localhost:3000
If it worked, your rails app log should show that params[:id] is a string. Otherwise, if you actually applied the official patch or updated rails to a patched version, it will actually show in the logs:
Disallowed type attribute: "yaml" # (or "symbol")
If the logs show it’s an object, it’s not patched. Let’s talk about this more, and make sure we get all the listed apps above (and any I missed) fixed. I just wanted to get all my thoughts written out.