Vulnerability in JSON Parser in Ruby on Rails 3.0 and 2.3
groups.google.com
groups.google.com
* Rails: http://www.cvedetails.com/product/22568/Rubyonrails-Ruby-On-...
* Django: http://www.cvedetails.com/product/18211/Djangoproject-Django...
* CodeIgniter: http://www.cvedetails.com/product/11625/Codeigniter-Codeigni...
* Top 50 Products (Better stop using these too! /s): http://www.cvedetails.com/top-50-products.php
Rails: numerous code execution and SQL injection vulnerabilities reported over the years.
Django: no code execution or SQL injection vulnerabilities reported.
How many times did you have to stay up late at night to patch your framework ?
* Python [1,2] : 20 + 15 = 35
* Ruby [3,4] : 31 + 8 = 39
* PHP [5] : 336
Ouch :(
[1] http://www.cvedetails.com/product/2147/Python-Software-Found...
[2] http://www.cvedetails.com/product/18230/Python-Python.html?v...
[3] http://www.cvedetails.com/product/12215/Ruby-lang-Ruby.html?...
[4] http://www.cvedetails.com/product/3861/Yukihiro-Matsumoto-Ru...
[5] http://www.cvedetails.com/product/128/PHP-PHP.html?vendor_id...
edit:formatting
Presumably a fairer comparison would compare (Python + Django) with (Ruby + RoR) with PHP?
It's safer to only use vulnerability counts as a metric for how interesting software is to security researchers.
As in, I use Rails to develop web applications. In the past months, I've had to painstakingly go back to every single app I've ever worked on, and manually update it in whatever minor way it needed updating. Now, I'm going to do that again.
If you consider that I'm going to continue to build Rails applications, the number of apps I will have to update every time a security vulnerability comes out will be larger and larger. For a framework that prides itself on sane defaults, it doesn't seem quite sane to have to worry about taking down, updating, and then relaunching every app you ever had when one of these vulnerabilities come out.
I don't mean updating a Rails 2.3 app to 3.2 automatically, just applying these security patches automatically, or prompting the user to do so. Our operating systems do it, our IDEs do it, our programs do it, why can't a framework? I'm not saying it would be easy, but I'm sick of having to be subscribed to these email groups just to start the manual process of fixing everything.
Or you could set up a cron-like worker to perform a pip-review (https://github.com/nvie/pip-tools) of sorts.
I don't know if I like the idea of a single point of failure; whatever service pushes the update would have a big, fat Wile E. Coyote target on its back.
I am currently trying to figure out something similar for a Django-based app at the moment. I include a version in the settings file that I plan on comparing against some sort of version array on a central website.
If a new security update is available, a conditional notification will show up for admins, but they will still have to update somewhat manually - I can't set up a cron job to trigger the whole procedure, especially because it might wreck their service, depending on how it works.
This is a solved problem though, right? Antivirus companies deal with this when they push out definition updates that render backdoors ineffective, and yet while they probably are targeted by the virus makers, they have been quite resilient.
A different version notation is needed to know whether the version delta between your installation and the most recent contains vital security updates.
Having said that I've never had problems with the having Linux automatically run the security patches for me.
For those with larger organizations and larger apps, it would be the same process that big companies do whenever a windows operating system patch comes out: they test, test, test, and once they are sure the update will work ok, they deploy the patch.
gem "rails", "~>3.2.0"
Then when there's an update, run: bundle update rails
Edit: fixed the gem directiveIt might be better to have a cronjob that nightly runs the bundle update command, then restart the server. But again, this depends on you being smart enough to realize this, which since we are talking about sane defaults, isn't something we might want to assume.
https://groups.google.com/forum/?fromgroups#!forum/rubyonrai...
I probably wouldn't allow a production app to update itself without human intervention.
gem 'rails', '~>3.2.0`
otherwise you could get upgraded to '3.3' or '3.4' which is more likely to break something.Most deploy scripts will look at your Gemfile.lock and update if necessary during the deploy (or just run bundle install every time, which won't give you a locked version error if your Gemfile.lock matches your Gemfile).
Rubygems and bundler makes updating your application stupidly easy. I blogged about it here: http://bottledup.net/2013/01/10/bundler-and-gemfile/ but if you have a good Gemfile and automated CI then all you need to do is `bundle update rails` and then deploy your code. This is at least as easy as using apt to update your stuff.
You need to be prepared at all times to deploy workarounds to newly disclosed security problems. Package managers can and do delay fixes to accommodate the lowest common denominator of users. You cannot run a high profile application and be at the mercy of whoever is administrating your OS package manager.
The problem is that it is simply untenable for all but the highest-profile sites. Finding good ops people, even in the bay area, is extremely hard. Most sites are only going to realize that a security update has been released when their package manager tells them it has, and updating that package is usually a 30s process.
The companies I've seen have a hard enough time keeping track of security updates with package management. For a small to medium team with two, one, or even zero dedicated ops people, asking them to custom-compile (for example) a webserver, ruby implementation, and other critical libraries (openssl, glibc, etc.), subscribe to the relevant security mailing lists, and follow along with updates and security patches is tantamount to having them leave unpatched vulnerabilities on their systems for months or even years.
If you ask your users to change passwords every 30 days, there are inevitably going to be a few who take it seriously and generate and remember secure passwords every single time. But the vast majority are going to use weaker passwords than they otherwise would have, and duplicate those passwords across accounts as much as they can figure out how. Likewise, if you ask already overworked ops guys to manually compile and keep track of security vulnerabilities for their webserver and dozens of libraries, a few are inevitably going to keep on top of things and release fixes minutes after vulnerabilities are announced. But the vast majority are going to simply give up after a month or two and be significantly worse off than if they just use Ubuntu's automatic security package updates.
That doesn't change the fact that relying on your OS package maintainers to properly update packages results in the same "having them leave unpatched vulnerabilities on their systems for months or even years" (at least the "months" part if Ubuntu is any indication).
This would seem to be a "damned if you do, damned if you don't" scenario.
Also, the 30 day password change thing isn't even something that's "technically correct". It's a "why do we cut the ends of the roast off" vestige from old DoD recommendations.
I'm not saying you need to be able to find your own nginx vulnerabilities or even write your own patches. But reinstalling nginx or Apache from source shouldn't be a science project for your team; you should know that you can get your prod servers running on a from-source build.
Sink in the time to make sure you can do that now, so you aren't caught totally flat-footed when an emergency happens.
But your audience here is startups. Almost always, these startups are cash-strapped, time-crunched, and have zero dedicated ops guys. Ideally, even these types of businesses would prioritize security to the level you're asking.
In reality, as I said in my previous comment, almost none of the startups I've worked at have had the ops capacity necessary to handle this. Even with package management, servers go months without having critical security patches applied. Asking these types of companies to do something that increases the ops overhead necessary to apply patches is going to result in a worse outcome. Keep in mind that it's not simply compiling from source and having infrastructure to apply security patches across multiple boxes. It's also keeping an eye out for reported vulnerabilities — and not all projects have dedicated security mailing lists. Not all projects even report this information via mailing lists.
I wish it were different. I understand where you're coming from. But the incentives are set up ass-backwards, and until companies start having serious liability for data breaches, protecting customer data simply isn't going to be a priority. In the meantime, encouraging them to set up their infrastructure in a way that requires even more ops effort when they're already struggling to keep up is going to have an adverse outcome.
It is actually practically correct. Theoretically, there shouldn't be errors. But there are.
Debian has a fix for the version of Rails 2.3 that they're shipping, but 2.3 is years obsolete, and officially unsupported upstream.
Pointers on both: https://bugs.launchpad.net/ubuntu/+source/rails/+bug/1097643
(comments in the Ubuntu issue reference the Debian fix.)
There are things that the Debian and Ubuntu maintainers do well, but their packaging for Rails and the underlying Ruby language have both been problematic for quite some time, and their use is generally not recommended.
Up-to-date security is one seriously important reason.
The problem is, with Rails, you'd never know when the self-updater would update you to a release that broke backwards compat and broke your app.
Still doesn't fix the fundamental problem though. Let's say you automatically install updates on a staging server and automatically deploy to production if all tests pass.
What do you do when you're faced with a choice of deploying an app with a few failed tests (for perhaps not totally clear reasons) or leaving an old version up with a vulnerability?
bundle update (if gem version is set with ~>)
You could easily automate this (cap,puppet,chef) if you have a lot of installs. If you genuinely don't want to test updates, you could run it on a schedule.
What it doesn't do, and can't do, is guarantee that security updates will never break your app, but they do quite a good job of isolating them, you do have to do some testing. There is possibly an argument for lts releases which receive few new features and focus on bugs, but what you're complaining about here are really the complexities of running multiple web apps/servers, not something a framework can really help with.
I don't think you have to worry about this update if you have already updated tho latest anyway (which you should have done if on 3.2.x).
You will still get this problem with browsers also for example. The amount of times a firefox update has resulting in half of my plugins breaking.
This points to a seriously broken process.
The issue is that similar projects, with similar success, with a similar number of developers looking at them, have fewer severe vulnerabilities.
The simplest explanation is that one project has more vulnerabilities lying dormant.
When a particular bit of code gets audited, you tend to find a bunch of holes. And any time you find a conceptual mistake that was made once in code, odds are that a careful audit will find it repeated.
Everyone thinks that they are different, until it happens to them.
http://www.hnsearch.com/search#request/submissions&q=dja...
Django has had its fair share of patches. This is no reflection on the quality of the project, as it shouldn't be for any sufficiently complicated framework (like Rails).
I also think the vulnerabilities are similar enough to suggest that the first one gave valid reason to ensure the same issue doesn't occur elsewhere. Rather than dusting these issues under the rug or silently fixing them, they're being responsibly reported with patches and updates provided at the same time.
This doesn't seem like broken process to me.
http://www.cvedetails.com/vulnerability-list/vendor_id-12043...
http://www.cvedetails.com/vulnerability-list/vendor_id-10199...
Django has 16 vulnerabilities of the DoS, XSS, and CSRF variety.
Rails has 37. In addition to DoS, XSS, and CSRF, it has SQL injection and code execution.
That we keep seeing similar vulnerabilities suggests the problem is systemic.
Giving them praise for not sweeping these under the rug is giving someone praise for not being a sociopath.
In my opinion, the fact that someone bothered to comb through 2.3.x and 3.0.x to find exploits similar to the last one points to a very good process, not a broken one.
Not all Django vulnerabilities have been discovered or reported yet. Just because no one has found or reported a vulnerability, doesn't mean that it it doesn't exist.
You need to patch. Now.
Definitely not saying you're wrong, but I'm not convinced this is doable. Every exploit I've seen requires a request body -- how would you do that with an IMG tag?
I'm actually going on a Rails security safari later, though not particularly looking to widen this/these vulnerabilities. I figure I've gotten enough out of the community over the years to contribute part of a workweek and get one more hole plugged.
One would think this is strictly less important than "root your server" but that hasn't been true for 100% of Rails developers that I've recently spoken to so, if losing your Macbook is the inducement you need to drop everything you are doing and patch, I will supply that inducement liberally.
Our old app runs 1.8.7, is there a POC out for that?
They won't always tell you if they have an exploit.
I think they wanted a json parser but they didn't want to write one. So they basically just wrote:
YAML.load(json.gsub(/awesomeregex/, "awesomereplace")) YAML.load(json)If you're on 3.1.x or 3.2.x then you should be good.
(Didn't expect to post this comment twice today, JFC)
We now need to ask ourselves, "Can we trust the Ruby community, and can we trust software written in Ruby?"
Before these recent exploits, there were a lot of us who would have already answered "no" to both parts of that question. Now there may be many more people who answer them the same way.
The warning signs have been there for a long time. The general attitude of the Ruby community is one of these warning signs. The smugness, the emphasis on "best practices" (which usually aren't very good, in reality) and the drama and semi-religious worship surrounding certain members of the community (DHH, Zed, and _why) are what I'm talking about. This kind of attitude promotes an environment where bugs can happen in the first place, then go undetected, and in many cases also go unpatched once discovered.
At this point, I think it's necessary to scrutinize the Ruby community and their software much more closely than has been done in the past. The complacency of the past is not acceptable any longer, given what has happened recently.
This seems to be something of a theme with RoR. XML parsers that parse YAML, JSON parsers that parse YAML, YAML parsers that parse Ruby...
Why would they let that mess near user input? I thought Ruby included a proper JSON parser now.
Non-bounds-checked arrays are fast and convenient to work with...until they can be exploited.
Database queries using interpolated strings are flexible and convenient to work with...until they can be exploited.
Serialization formats that can encode arbitrary objects are useful and convenient to work with...until they can be exploited.
...and the collective wisdom of the programming world continues its relentless, gradual, monotonic increase.
find ~/rails -name 'Gemfile' -exec grep -E "rails', '3.0" {} \; -printIs there some magic command I am missing to update all rails projects I've ever worked on automatically?
"gem super-update-everything"
Happy hacking!
Awesome.
Is it the lovers wanting to spread the word for their rails colleagues using it.
Or is it the haters enjoying the schadenfreude.
No other framework seems to get as much publicity on HN whenever something goes wrong.
It started with such promise, and now, we are looking to migrate all Rails apps off to alternative frameworks at the first opportunity. It really is a shame.
As above, so below.
This is not to diss Symfony, on the contrary, I believe having vulnerabilities detected does not mean the framework is insecure or not to be trusted.
What's not very logical is changing frameworks to another with a similar track record on the security camp due to some vulnerabilities found.
> Symfony applications are not vulnerable to this attack
And it definitely has not the same track record. For example, it has been audited by a security company in one of the first versions. So far I have only seen minor security vulnerabilities, nothing like what Rails brings every week.
Anyway, that's not why I changed. I found it to be much better architected, 100% decoupled (as opposed to monolithic). You can change anything you want if you have to, or if you find better vendors and want to try them. It has actually been designed from day 1, and not by someone who has read about design patterns little time before creating the framework, and calls himself 'the master chef'.
Having an OOP background, I thought (I don't remember why) Ruby/RoR community was some sort of elite, and everyone had a much higher minimum level (as opposed to php, where most people are noobs). I was disappointed, most of them didn't even understand what interfaces were for (no wonder ruby hasn't added them yet), let alone knowing the most basic design patterns. They also seem to enjoy laughing at developers from other languages. All this was a pain to watch, but I didn't care as long as Rails was perfect, and that's how I felt about it at first. But it wasn't, so I moved to Symfony2, and found out not only the framework was superior, but also the community was awesome.
And that [found vulnerabilities per time unit] * severity = [overall product security] is a fallacy in general.
In fact, showing that symfony has had vulnerabilities was a good thing in my book.
Anyway, it's great you've found some framework you feel comfortable with. That's an awesome thing to have.
That just doesn't logically follow: your chosen alternative framework just might have not been thoroughly audited (yet.) Or not audited by the right people, etc.
You are free to dislike Rails design, but you can't blame it for some vanilla parser bug.
Parsers are fertile ground for bugs, because they are by definition exposed to arbitrary input.
They implemented the JSON decoder with a JSON to YAML converter, passing that through the YAML decoder.
The fix involves using an actual JSON parser and skip the going through YAML part. So it does qualify as a JSON parser bug, IMO (which is what I clumsily attempted to imply with my "(or JSON)" clause above.)