Rails SQL injection vulnerability: here are the facts
blog.phusion.nl
blog.phusion.nl
Wish there was more I could say right now. I'm not saying I have a curl command that exploits the vulnerability. I'd just be careful about making assumptions about this bug.
The goal of the article is not to defend Rails. It is to inform about the nature of the vulnerability and to replace the feeling of panic with rational thoughts.
They had this attitude when it came to the maintainability of Ruby apps. They'd say that Ruby code was much more maintainable than Java code, for instance. Now that we've got some Ruby apps that are several years old, and that have been worked on by a number of different people, it has become quite apparent that Ruby code is much less maintainable, over the long term, than Java code is.
This same attitude was shown when it came to Ruby's performance. Many of us had serious misgivings about just how poorly it performed, and the suitability of Ruby on Rails for anything beyond simple sites. Then when some Ruby on Rails sites started facing moderate traffic, they basically collapsed. The answer from the Rails advocates was to "throw more hardware at it".
We even saw this same attitude when it came to this very issue. We'd heard about how Ruby on Rails is far more "secure" than alternatives. Yet that's proven not to be the case.
When Rubyists make claims, it's best to doubt what they're saying, and to question every single detail about it. They have given themselves a bad reputation for making incorrect statements.
I'm interested on the "maintainability" claim, though, because that one is new to me. Are there any blog posts that make this claim with some kind of example?
It comes from prejudice and fear about the lack of compile-time checks in dynamic languages. I know this personally, because I remember starting out with Python, and Java and C++ felt very safe — on a visceral level — in comparison, and Python felt very unsafe. I have since learned to recognize these feelings as irrational and unfounded.
Any language allows you to shoot yourself in the foot, in different ways. It's just as easy to write an unmaintainable app in C++ as it is in Ruby.
I'm sure you can find numerous blog posts out there describing the maintainability problems with Rails web apps. Google for them. The fact that you're looking for blog articles makes me think that you may have limited experience with large-scale software development projects, especially those spanning many years and development teams.
Have you ever worked on large, long-running C++ or Java projects, for instance? If you have, then it should be pretty obvious to you how inadequate the maintainability of Ruby code is. Ruby, and dynamic languages in general, lack much of the functionality that makes code maintainable after many years, or even decades. I really wish you did have this sort of experience, because I think it would make the maintenance issues more more obvious.
I want to see people who have written "the fact that this project is in Ruby is the bane of my existence and here is why these problems would not have occurred in my language of choice".
>lack much of the functionality that makes code maintainable after many years, or even decades.
This is just FUD. LOL, what inherent property is this that makes it maintainable?
Great trolling, btw.
I agree that there are performance issues with Ruby implementations such as the MRI. That's really part and parcel of an immature implementation, that is, it hasn't received the millions of developer man hours spent fine-tuning it, such as the Java ecosystem has received. However, I would observe that it's still easy to get Java performance very wrong. It turns out that efficient GC is hard -- really, really hard.
> Yet that's proven not to be the case.
You have a proof of that? Care to share?
How does one even prove framework X being more secure than framework Y? > When Rubyists make claims, it's best to doubt what they're
> saying, and to question every single detail about it. They have
> given themselves a bad reputation for making incorrect
> statements.
Would you mind to reveal, what kind of -ist you are, and why the -ists you represent make only absolutely true claims?
Or can we just agree, that this kind of generalization is silly and pointless?There's no singular Ruby community anymore than there's a C, PHP or "Linux community" whose behavior can be collectively judged.
Anyone who has been to a Ruby conference, especially while not being overly involved with the community otherwise, would likely know what I'm talking about, for example.
Almost the entire community is male. There are very, very, very few females involved. While other communities have an imbalance, it is nowhere near as lopsided as it is within the Ruby community.
Another common trait is the use of Apple hardware. It's rare to see anything but Apple laptops or other devices being used by those within the Ruby community. I've been at talks where there are rows of 20 people, and over 15 of them are using a MacBook of some sort.
There's very little true dissent within the community. The emphasis on "convention over configuration" ends up chiseling those conventions into stone, and nobody dares question them, even when they're obviously wrong.
While I'm not saying every single member of the Ruby community is exactly like every other, there is a commonality that is not found in any other computing community. It's undeniable.
I work with three other Ruby programmers, two of whom are female, and older than me (I'm 30). Your assertion that there are "few females involved" might as well be characterization of IT in general for all the evidence you present. In my experience diversity is a reflection of institutional values, not the culture of the programming languages used.
Apple hardware is tremendously popular with web developers in general, and while I don't blame you for your impression (I've been to RailsConf), there are plenty of Rubyists who prefer Linux on a Thinkpad. I bet you could find rich veins of Apple hardware at almost any type of conference.
There is plenty of disagreement about the best way to do things; that's why we have both Rails and Sinatra (both of which have been imitated in Python, node.js, and more) several implementations, and lots of discussions about new language features (like refinements).
I suspect your confirmation bias means you don't even notice Rubyists who don't fit your preconceptions.
Of course there are Ruby, C and PHP communities. They do not include every single person and they can be more or less homogeneous when compared to each other.
Ask the people who are trying to build healthy communities around a new language or project if they think that these don't exist or don't matter or can't be worse or better than other communities.
This issue is is built up to be serious because many people seem to enjoy attacking rails and the community despite not realizing that the vast majority of the community is amazing. If there's a burning need to criticize ruby/rails, discuss Ruby's terrible garbage collection, or the state of MRI or Rails' lightspeed rate of change.
But that is not what people mean when they say this isn't a severe bug. They mean, "I read some article where some guy said you needed the right HMAC key on a cookie to exploit the bug", and I think that article is wrong, and thus the assertion about severity is wrong.
It is a severe bug with an easy fix. Unfortunately I think there are some other bugs orbiting around it that don't yet have fixes.
That is definitely not the intention of the article. There are other exploitable scenario and the reader is encouraged to check his code base for those instances. The article merely spends many words on what I believe would be the most scenario. The severity depends on the codebase.
You're only looking at part of the picture, I think. It's not just a matter of asking, "will the site hold up?", but rather it's one of "will the site hold up, given an economically-feasible amount of resources?"
Throwing a lot of resources at a Ruby on Rails site for one day of heavy traffic is one thing. Having to do that for years on end just to maintain a reasonable level of service in the face of growth is a very different thing, and far closer to the reality that we have to deal with.
A recent project that I've been involved with switch from Java to Ruby and they reduced the number of servers by 10 times (!). But I don't blame Java, I blame the programmers of the last code base. You can write unmaintainable messes in any language.
I once interviewed a Rails developer who was bragging about a Java-to-Ruby conversion he'd worked on. He was proud that they went from 50 servers running the Java system to only 30 for the Ruby one.
Upon further questioning, he admitted that those 50 servers used by the Java system were from 2003, and the ones powering the Ruby-based system were from 2011! They didn't even halve the number of servers required, but the new servers were many, many times more powerful than the old ones.
The security practices i saw are nothing short of ridiculous. If you'd take all the rails vulnerabilities and put them in a pot, and compare them to the holes i've seen in the little time i looked at them it's like comparing a secure vault to swiss cheese.
granted, saying x is secure, because y is inherently insecure is not a valid argument, but i've seen people first hand use these exaggerated advisories to justify that their bug ridden insecure enterprise stack is more justifiable for the enterprise. these people did not know pbkdf2, bcrypt, and even the sql injection whitepaper by microsoft(which btw is a joke).
wanna write secure code? NEVER assume someone else is going to secure it to you. fact is, good advisories and quick reaction to those are not a weakness but a strength.
You want to know the state of encryption in the enterprise world? Get a recent pastebin hack dump. Databases with passwords in plaintext, passwords in md5.
as for your sites basically collapsed? yes they did, it got popular during ruby 1.8.5 ffs. what the hell do you expect? it's slow? well, that's why theres lot's of custom c around. but anyway, since then many many things changed.
Java maintainable? In which world do you live? 8 different layers of OO abstractions 20 levels of dot notation, in which world is that maintainable? Notice how people move to groovy, scala, and other things, not plain java? ever wondered why?
You want highly reliable systems, your answer is not going to be java. Try erlang, but that one is GENUINELY slow.
Oh wait, did I even mention jruby? There you go, all the Java you want, kinda.
Basing an argument about technical things on "what people say" will not succeed, no matter what your goals are.
Edit: I shouldn't have been so harsh since the author is a security researcher and is probably not doing it out of some grudge. But even from a security researcher, saying he has doubts about a software doesn't make something insecure.
If he can prove his statement that he thinks regular user input is insecure (without requiring the secret session key), then I will happily be convinced of his prowess in finding exploits.
EDIT in response to upsteam edit: He did imply that you should wait for the upcoming Rails advisory, so you'll get your proof then.
Based on Charlie's PoC I managed to sneak a SQL-injection into some really basic ActiveRecord queries. It's not entirely obvious how to accomplish this, but it wouldn't surprise me if other people who discovered the same bug will find similar exploits.
This has been reported to Rails' security team and I expect patches to be released pretty soon.
For now I don't have an easy-to-apply workaround that doesn't disclose the gist of the exploit.
http://edgeguides.rubyonrails.org/4_0_release_notes.html#ext...
I have no idea why THIS vulnerability is getting so much attention. There have actually been OTHER Raisl vulnerabilities in the past 6-8 months which were _more dangerous_, but did not really get attention.
The Rails team did NOT help by being very vague about the nature of the problem in their announcement. I imagine they were trying to not reveal the method of exploitation; but it has just led to the current hysteria instead. They would have been better off being taking the extra time to be fully transparent about the nature of the vulnerability -- developers need to know to assess their own risk, as well as to judge the quality of Rails (how stupid was the problem exactly, what does it say about Rails etc?), etc. By being vague about it, Rails core team has just led to everyone assuming the worst, and the current weird hysteria.
Yes, it's a vulnerability which COULD be dangerous, and it's hard to tell FOR SURE if your app is vulnerable (perhaps due to code in gem dependencies), the only safe thing to do is update to a patched version. But the chances that your app is vulnerable are pretty small (if you aren't using AuthLogic; if you are, you can update auth_logic and fix it whether or not you update rails). And past recent vulnerabilities which were actually MORE dangerous have not received this level of attention.
Its getting attention because its the third SQL vulnerability in 7 months. It just feels like Rails is mature enough at this point that it shouldn't have to be going through this now
But the fact remains that THIS vulnerability isn't NEARLY as dangerous as some of those OTHER ones you mention in the last 7 months, but those other ones people mostly ignored, and THIS one they're going crazy thinking they need to fix right away.
What I think about the general question? Most (all?) of those Rails SQL injection bugs actually are related to a similar underlying design: Attempt to create methods with 'variable signatures', where you can give it a string OR a hash, or a list of various strings and hashes, and all of those things mean different things.
I think all of the Rails SQL injection bugs are actually related to variable arguments like that. When those variable argument methods were designed in Rails, it's probably safe to say nobody realized there were security implications, that it opens you up to a whole class of bugs where someone puts a hash where you expect a string and it change the semantics of the method call because your variable argument interpreting logic had some flaws. In retrospect, it's possibly not a great thing to do.
But Rails is not the only offender here, it's a pretty common design pattern in lots of ruby -- I think it's probably a mistaken one, but it is one that developers tend to like the convenience of.
What I still think this shows is that trying to keep information on the nature of the vulnerability to yourself is not a great idea. People who figured "Well, there's no way for params[:id] to be a hash with a symbol key" (such as myself) were wrong about the severity of the vulnerability.
It would have increased everyone's security to admit "Oh yeah, there might be a way to make params[:id] be a hash with symbol key even though you don't think so, yes you should worry about it."
Why not do that? Becuase you're worried you're giving someone exploitation hints, probably. But anyone that wanted to exploit had all the hints they need anyway -- as evidenced by the half dozen people credited with reporting the new vulnerability, all of whom got the hint from the 3.2.10 announcement anyway.
You should take this bug very seriously, and also pay close attention to Rails security releases for the next couple of weeks.
Other exploitable scenarios
Your code is vulnerable if you call Foo.find_by_whatever(bar), where bar can be
an arbitrary user-specified hash with symbol keys.
This is a fundamental flaw that requires a very specific set of circumstances (which the Rails community is clinging to as a get out of jail free card), similar to the Python Pickle boondoggle [1], which will result in lots of application specific vulnerabilities down the road.Get your facts right first. It's not a Ruby bug. It's a Rails bug. Ruby != Rails.
Many words are used to explain how it works. That is not a refute, nowhere did I claim the bug does not exist. But the requirement for specific circumstances is a fact.
The Python pickle example is not only totally irrelevant, it is also not a security vulnerability. Pickle does exactly what it is supposed to do. You weren't supposed to unpickle arbitrary untrusted data in the first place. If you require a safer alternative, use JSON or something, but don't expect as many features as pickle provides.
In the end, whether this is a "bug" or a "huge bug" is left as an opinion. The article provides hard facts, and a little bit of commentary. Fact is, we've written a ton of Rails apps that all use find_by_* quite extensively but none turned out to be vulnerable because the case where 'foo' is a symbol hash is rare. Whether you think this is an excuse or not, I'll let you decide.
I would understand "huge Ruby on Rails bug", though, by convention, it is still a fairly unlikely case.
Edit: I think your edit answers my "Could you elaborate" question somewhat, as you relate a Python library issue to this issue.
This, on the other hand, is just a Rails bug. It has a simple fix. That fix is provided transparently by Rails. It isn't going to cause "lots of application specific vulnerabilities" because nobody is going to care about it 6 months from now, except as yet another reason to keep Rails at the most recent version. This is a problem no different from that faced by people on J2EE stacks.
So I disagree with both of your points.
Sounds much more sexy and they can do more Rails bashing that way. The fact is true as you and the article says, it's pretty obscure. In addition to being obscure, you need the secret session key.
So I'd characterize it as a serious problem, but not widespread in the wild, and also with some unknown risk that another major gem like AuthLogic could be as-of-now unknowingly extending the footprint of the vulnerability.
So it is pretty obscure unless you take user input and do something pretty special to make it return symbols and then run find_by_whatever on it.
Though if that was easy it would most likely have been caught much, much earlier as there are a multitude of find helpers that allow literal SQL to be injected.
The end user ends up repeating themselves less, but that means that the library code ends up getting used in lots of places and for lots of purposes that the author didn't necessarily think through...
So yes: "copy pasta" of the id boilerplate around an AR find() call would absolutely have prevented this. Rails got slick, and got burned. DRY helped reduce "copy pasta" (sigh) but hurt security.
DRY as a general philosophy to avoid cut-and-paste code is fine. But it's also an ethic that in my experience prioritizes concision at the expense of clarity. Loss of clarity is a factor in half the security bugs on the internet.
But - I'm confused why one of the readers on the post (Jonas) is calling this a PR Stunt?