Rails Ticket 4339 suggests that there is a denial-of-service vulnerability because of the way the Rails request handler instantiates a symbol for every incoming request method. This is technically true, but turns out not to matter, as seen below.
help i’m allocated and i can’t get released
There are only a few valid HTTP request methods:
PUT, etc. But Rails creates the symbol before it figures out what to do about it. If you make a
FOO /index.html HTTP/1.1 request, Rails will instantiate a
:foo symbol. As you know each unique symbol requires ~60 bytes of memory in the Ruby intepreter and is never garbage collected. The idea is that by spamming the server with lots of bogus request methods you can exhaust its memory space.
It’s easy to write a script to exploit this with a small change to rfuzz. I ran such a script against a localhost-mounted generic Rails app (the ever-present cookbook example). The test environment was a dual-core Intel Mac, one mongrel process, production environment, and terminal output redirected to
/dev/null. I increased the number of attempted simultaneous requests until the mongrel thread reached 100% cpu usage.
|Rails memory usage at start-up:|
|time||real memory||virtual memory|
After one hour of fuzzing:
I should have counted how many requests were made, but I didn’t, for the sake of speed. We can guess, though. 35.09mb / 60b = 613,242 maximum requests.
The upshot of this is that a successful exploit of this issue entails a fierce regular-style denial-of-service attack. On a real network, the sheer number of requests will cause more issues than the possibility of eventually crashing some mongrels or fastcgi processes. So basically, it doesn’t matter.
Also, this will be fixed completely with the new symbol handling in Ruby 1.9, since then
Symbol will go out of scope and get garbage-collected like any old