Posted by Nick Sieger
Wed, 15 Nov 2006 15:46:00 GMT
Inspired by a posting on the RSpec list and recent comments stating that my Auto RSpec hack wasn’t working, I’ve bitten the bullet and upgraded to RSpec 0.7.2, and made rspec_autotest a plugin in the process. So, herewith are the necessary incantations to auto-rspec your project. If you’ve tried my hack already, please remove any bits you previously had installed.
- Install RSpec on Rails, following the original instructions. As of RSpec 0.7.3, the specific version of ZenTest is no longer required. Also, diff-lcs is required to show unified diff output on
should == failures.
gem install zentest -v 3.4.1
gem install diff-lcs
gem install rspec
script/plugin install svn://rubyforge.org/var/svn/rspec/tags/REL_0_7_2/vendor/rspec_on_rails/vendor/plugins/rspec
script/plugin install http://svn.caldersphere.net/svn/main/plugins/rspec_autotest
Please let me know if you experience any problems!
Tags plugin, rails, rspec | 15 comments | no trackbacks
Posted by Nick Sieger
Tue, 15 Aug 2006 04:12:00 GMT
What was the biggest security threat story for me last week? No, it
was not the disrupted liquid bomb plot, it was the Rails
security hole that caused quite a brouhaha among the Ruby
community. (Guess that shows my increasing tendency to lose touch
with reality. Maybe a sign of the miserable state of unrest in the
world and how living in the land of the world’s only super-power makes
it easy to turn the other cheek? Or…ok, ok…it’s just me.)
From my view of the Rails security issue, there are actually quite a
few interesting angles that came out of this story.
Rails is Growing Up
This is the obvious one. The first major fault to be discovered in
Rails shows that Rails the codebase, Rails the core team, Rails the
technology stack, and Rails the community is going through growing
pains. David was both praised and criticized widely for his handling
of the disclosure. Many rightly complained that the initial
announcement didn’t give system maintainers enough information to
decide whether the risk warranted disrupting normal operations to
spend time to test and roll out the patch. This was compounded by the
fact that the initial announcement did not identify versions affected
and instead assumed all past versions, which turned out not to be the
case.
Others thanked the Rails team for their discretion and trusted the
recommendation despite the fuzziness and lack of details. These folks
either were able to perform the upgrade much more easily or had some
inkling of just how serious the issue was.
The aftermath showed that the Rails core quickly learned from the
experience. A security mailing list and google group were
set up for future incidents and David promised to apply more rigor
and policy to future announcements.
It seems pretty obvious that the size of the gaffe was such that to
expose the details immediately would have had way too much potential
to cause widespread data loss and denial of service. In fact, the
nature of the bug strikes me as one of those embarrassing bugs that
every software developer commits at one point in their coding life
where you amaze yourself at the short-sightedness of your
implementation. I think the initial message could have been
dispatched with information on the severity of the threat without
necessarily disclosing the exact exploit. So, essentially I agree
with the approach that was taken, but the message left out details
required to evaluate the threat.
Threat Analysis
Two early blog posts came out the day after
claiming to know the details of the exploit. It turned out that they
didn’t quite understand what was afoot. (Although Evan Weaver has
since updated his post to clarify his original analysis.)
The threat turned out to be a simple remote code execution issue. The
:controller dynamic expansion aspect of routing contained a bug that
allowed arbitrary .rb files in a Rails application to be executed
undesirably. By far the most dramatic consequence would be
experienced if one’s db/schema.rb file were to be executed with a
request for /db/schema, causing your entire database contents to be
dropped and reloaded.
By examining the safe_load_paths method defined in affected
versions, it appears that the implementation tried to limit elements
of the load path that matched the expanded RAILS_ROOT of the
application. Combine this with the fact that other elements of the
routing system eagerly require‘d files with inadequate
bounds-checking spells your recipe for disaster.
Many posters and commenters quipped that a simple svn diff was
enough to give script kiddies or other black hats the information
needed to exploit the issue. Or was it? Given that the two early
analyses turned out to be off the mark, were people in the know
exercising more discretion by not disclosing more details?
Personally, I spent more than an hour staring at the affected routing
code trying to untangle the various metaprogramming tricks and regular
expressions that make up the Rails routing system. And I consider
myself fairly adept at reading and understanding code!
The truth of the matter is that, unless you’re a member of core or
have a high level of familiarity and involvement with the Rails
codebase, the svn diffs provide far too little context to decode the
actual problem.
Does this speak to the obfuscated nature of the Rails codebase or to
the relatively advanced nature of web programming in Ruby? If I had
to pick one, it would be the latter, but I’m leaning towards neither.
The Rails codebase is not the most readable, comprehensible piece of
code I’ve ever seen, but it does its job remarkably well. Perhaps if
the routing code in question was a bit more understandable by the
masses, this rather obvious security issue wouldn’t have gone
undetected for so long.
Post-1.1.6 Release Triage
A group of enthusiastic Railsers jumped onto #rails-security on
freenode shortly after the 1.1.6 release, where an effort had been
organized to verify all the patches across various combinations of
web servers and Rails versions. An IRC channel, a wiki,
Ruby, Zed’s RFuzz, and a piece of code were all the
tools required to get a distributed test verification process up and
running. This sort of thing happens all the time in the open source
world, with programmers around the globe pitching in to raise the
triage tent of the MASH unit. Still, it was exciting to see and be a
part of the action and to be reminded of the power of the collective
whole working for a common cause.
Dynamic Routing Harmful?
Rails’s dynamic routing code came under fire too, understandably so.
Maybe this is one case where the developer-friendly approach of
magically recognizing URLs goes a little too far? Production-only
routes that do away with the expandable path elements could easily be
generated by visiting all the controllers in the codebase and
generating a more static route for each – sounds like a good idea for
a plugin. Perhaps the controller is the better place to store routing
metadata anyway?
class UsersController < ActionController::Base
map_default_route
end
class PostsController < ActionController::Base
map_route_as_resource
end
Sounds like good fodder for future investigation!
Posted in ruby, rails | Tags rails, security | no comments | no trackbacks
Posted by Nick Sieger
Mon, 15 May 2006 03:12:00 GMT
Tom and Charlie have just experienced what can only be described as a watershed moment in the grand scheme of dynamic languages on the JVM. The Rails experience may soon be visiting a Java application server near you! Even though JRuby will be in perpetual catch-up mode with C Ruby, Tom and Charlie and the rest of the JRuby contributors have shown incredible perseverance in tracking the Ruby language despite the lack of any formal specification. Maybe Rails will never be mainstream, but the possibilities just got a whole lot more interesting. I agree with Obie that this could be a game-changer.
Now, a few comments about the ActiveRecord JDBC adapter. This code can still be considered alpha quality at best. It’s awesome that Tom and Charlie will be able to demo a top-to-bottom, working Rails app on JRuby, but don’t jump to conclusions yet that this will be anything like a write-once, deploy-to-any-database kind of experience. But you didn’t think it would, did you? We all learned that about Java a long time ago, right?
You can check out the code here. At the moment, I’ve only tried it with MySQL. Most of the problems with it come from the lossy mapping from ActiveRecord’s abstraction of the database to JDBC’s. (Although I suspect as more JDBC drivers are tried that there will eventually be compatibility issues with different implementations of the JDBC spec.)
Probably the thorniest issue is the one of type conversion. ActiveRecord has a fairly simple notion of types: :string, :text, :integer, :float, :datetime etc. Compare this to JDBC’s. What a mess! Right now there are arrays of procs for each AR type that try to guess the best JDBC type to use. This will certainly need improvement to become a more robust solution.
Probably the most promising approach may be to create a patch that refactors much of the AR adapters’ type conversion methods into separate modules that could be included into instances of the JDBC adapter depending on the underlying database. Then the JDBC types wouldn’t be needed at all – the existing AR database metadata could be reused. Presumably this would require some petitioning of the Rails core team to accept the changes even though the changes don’t buy AR itself any additional flexibility.
If you have a chance to try out the code or can think of any additional tricks that would help the ActiveRecord JDBC implementation along, let me know!
Tags java, jruby, rails, ruby | no comments | no trackbacks