My name is Joe Basirico, I help people build secure software. Learn more »

Ruby open allows command injection if user controlled

6/3/2015 - Posted by joe

We've been getting a lot of Ruby on Rails Penetration tests and code reviews at Security Innovaiton, and I've been writing a decent amount of it myself. In general it's a great framework, but like any other framework there are a few little gotchas that could lead to a security vulnerability. A colleague of mine, Arvind, wrote a great blog post on the Security Innovaiton blog in which he outlined a few of these check that out here.

I also came across this on a blog post in this case using open('|[my-command]') will cause the code to be executed. open('|ls').each{|i| puts i} would output each item in the current working directory, for example.

Open is commonly used in ruby to open files, of course we all know everything's a file, but using it this way to get command injection is pretty cool. So any time you see user controlled filenames in an open command it's not just remote file read any more, it's full on command injection.

I originally thought that by using the OpenURI gem, which is common in Rails to load remote http content, this file based command injection may be overridden, but that's not the case.

Instead, I got looking into the difference between the default open (which comes from File.open), and OpenURI (which comes from the open-uri gem). OpenURI is very common, it's essentially the goto way to read a website (like wget) in Ruby. OpenURI patches the default open (Does not replace functionality) to support URIs, so it's still vulnerable even after the gem is included. http://sakurity.com/blog/2015/02/28/openuri.html

So, lesson learned, if you see open(my-var) in source code it's vulnerable. That's in addition to backticks, eval, Kernel.exec, IO.popen, etc....