Every other web stack has this problem in one form or another; for instance, in J2EE, which is either the first or second best-secured web stack out there, you can bypass the best-known best-documented access controls by changing your HTTP verb from "GET" to "SUPERGET", "GETX", or "GIMME".
But Rails kind of went out of its way to win this particular vulnerability, and so now it's something you have to audit for on every project.
Rails is moving so fast now that most sample code is very outdated. Take authentication for example, there's at least 5 different plugins, all favoured as the best way to authenticate in rails at one time or another. Totally hopeless for a newbie to dig out which is the solution to go with, or at least it's a few days trial and error, trying out tutorials here and there. I've done a few rails projects on and off and each time I come back there's tons of new stuff, which is really great, but I would personally like to have more batteries included or "blessed" official plugins because I don't spend all my time in rails land, and it's hard to keep track of all the new goodies.
Really interesting article.
I believe that security should be the default, automatic choice, and you should have to take an affirmative step to disable that when you need to.
Rails does get a lot right with automatic cross-site request forgery protection and nearly automatic SQL injection protection but the lack of automatic HTML stripping and the default accessible attributes thing makes me sad.
You're right that taking positive action to neutralize metacharacters is a weak design. There is a setting in Rails, IIRC, that automatically h() filters outputs, but it should be the default. Just as importantly, though, even if h() is the default, you still have to audit all the places where you deliberately allow HTML output, and every app has to do that somewhere.
I'm not disagreeing with you, but I am saying that there's a major difference between mass-assignment, which is a problem Rails seems to have blundered into, and XSS, which is endemic to web apps.
Developers in those frameworks must explicitly say that they want to display HTML in order to have it displayed. Presumably, they have thought about this and also taken action to remove bad HTML from this output. When you have to make a choice to display it, it makes you think about this.
There is no setting in Rails to automatically escape HTML. There is Erubis, which is a replacement for Erb that can do it, and there are some XSS plugins that escape input on input or output.
I'm saying escaping HTML on output should be the default for the framework.
There's a big religious debate inside the Rails community about autoescaping, which ran aground on the point that autoescape doesn't actually stop XSS. I agree with Rails, but concede that reasonable people could think otherwise.
It's hard to see how reasonable, well-informed people could think that mass-assignment was a good default feature.
However, I would argue that nearly every Rails app does have susceptibility to these "trivial" attacks because Rails does not force you to think about when you want to display HTML.
I also agree that people disagree on this. But I still feel the default should always be the secure one.
It's not the "escape" that's the problem, it's the "auto".
I feel like I've used template languages that actually understand XML (or HTML) and thus have context sensitive escapes. It was probably written in something gross like Java, so URLs were output verbatim in links, while say instances of "/search?q=" + someVariable would url escape someVariable in links, and html escaped in tag contents.
Stripping HTML on input also means you lose the ability to audit attempted attacks against your site.
A much smarter strategy in my opinion is to escape everything on output. That way it doesn't matter what people submit to your site - unless you explicitly say "this is safe to display unescaped" in your templates harmful characters will be neutralised.
(Incidentally, the reason why this will probably never happen is that it would break all of Rails' HTML helpers.)
There are several frameworks that do this already. Django even broke existing apps to make such a change.
And it was considered common knowledge back then. And most people don't fix it using attr_protected, so are we really sure that all those projects are vulnerable? A simple string search would not suffice.
Come to think of it, I learned a lot of good practices from AAA (and restful_authentication). attr_protected, salted/hashed passwords, and several other nifty tricks.
If the entire USP of your platform is that it cuts corners you'll see it put to use by people who either don't care or don't know any better.
I'm not saying there aren't good rails developers, but in my experience they are a minority.