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.
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
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.
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.
Comments are loading...