rails security note

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: GET, POST, 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.

whatever man

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
7:54am 21.04mb 51.24mb

After one hour of fuzzing:
8:56am 37.5mb 69.87mb

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.

silly strings

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 String.

One response