JSON-parsing YAML Vulnerability in Rails (and bonus patch for 2.2.x)

05 February 2013
I just realized this has been sitting in our drafts folder since just after the exploit was discovered. We're publishing it now in case it's still helpful to anyone.

This exploit is similar to the XML vulnerability explained in our last post. This exploit, however, is in the JSON parsing of Rails 2.3.x and 3.0.x, due to the fact that the built-in JSON parser in those versions of Rails delegated a lot of its logic to the YAML parser. The exploit and official patches were announced here on the official RoR Security mailing list.

This exploit also affected Rails 2.2.x versions, however, due to the fact that it was no longer actively maintained at the time this exploit was discovered, there was no official patch provided. We've supplied here a back-port of the official 2.3.x patch. It is supplied as-is with no warranty or guarantee as to its affectiveness or the absence of any side-effects.

The patched code was in this file in Rails 3.0.x. The related (but different, due to the different structure of the decoding libraries) file was this file in Rails 2.2.x.

Modified PoC for Rails 2.2.x

First, to test if your Rails 2.2.x app is vulnerable, download and run the following PoC file against your locally running Rails app. It's a version of the original Proof of Concept exploit script provided by the Ronin project.

↬ Modified JSON vulnerability PoC for Rails 2.2.x apps

This modified PoC, along with the following patch were originally posted by me here on Hacker News.

If you run this and see in your Rails log something like

"params = {#<ActionController... => {default => :action}...}"

...then your app is vulnerable.

We also have a couple apps we know of that are really old Rails 2.2.x apps. This doesn't work with them, because the passed YAML doesn't work in the old YAML parser. But then, if you just trust that deserializing an object from YAML in parameters is bad, then we can just make a super simple hash object and check our rails logs to see if the params contain an actual hash object. Below is an even more simplified version of the PoC to test older Rails 2.2.x apps that may be easier to run with older apps.

↬ Simplified version of the JSON PoC for Rails 2.2.x apps

Just to clarify and reiterate, the above modified PoCs require access to the Rails app logs to check if they worked or not, since the older Rails apps could error out for YAML-parsing reasons (which are just as bad, because it just means an attacker needs to get more creative with their YAML payload), instead of being a result of rejecting the attack. That's why I don't think a web-based attack mechanism like this could really know 100% whether or not an app is vulnerable unless it really tried doing something semi-malicious, like obtaining secret information.

Rails 2.2.x patch

Download Rails 2.2.x patch

To install it in your Rails 2.2.x app, first, you have to vendor the Rails gem so that you can patch it in the application code. In Rails 2.2.2, that means running from the command line rake rails:freeze:gems. This will put the version of Rails your project is using into app_root_dir/vendor/rails.

Then you can apply the attached patch, which was my translation of the rails-supplied 2.3 patch, but to be compatible with the Rails 2.2 JSON decoder.

Once you apply this patch and restart the server, when you run my modified PoC script, you should see in the Rails logs a Failsafe error for something like syntax error at --- ruby..., basically the part where it tries to instantiate a ruby object from the new non-YAML based JSON parser that the patch implements.

About the author:

Steve Schwartz // Owner of Alfa Jango, CTO of Genomenon, co-founder of Carcode (acquired by Edmunds.com in 2014), engineer, developer, open-source enthusiast, guitarist, and racecar driverist.

Comments are loading...