Forming sanitary shell commands or system calls in Ruby

arbales picture arbales · Jan 10, 2011 · Viewed 10k times · Source

I'm building a daemon that will help me manage my server(s). Webmin works fine, as does just opening a shell to the server, but I'd prefer to be able to control server operations from a UI I design, and also expose some functionality to end users.

The daemon will pick up actions from a queue and execute them. However, since I'll be accepting input from users, I want to make sure they're not permitted to inject something dangerous into a privileged shell command.

Here's a fragment that exemplifies my problem:

def perform
  system "usermod -p #{@options['shadow']} #{@options['username']}"
end

A gist that explains more: https://gist.github.com/773292

I'm not positive if typical escaping and sanitizing of inputs is enough for this case, and being a designer, I don't have a ton of security-related experience. I know that this is something that should probably be obvious to me, but its not!

How can I ensure that the web application that will create and serialize the actions can't pass dangerous text into the privileged process that receives the actions?

Thanks for the help
arb

Answer

cam picture cam · Jan 10, 2011

It doesn't look like you need a shell for what you're doing. See the documentation for system here: http://ruby-doc.org/core/classes/Kernel.html#M001441

You should use the second form of system. Your example above would become:

system 'usermod', '-p', @options['shadow'], @options['username']

A nicer (IMO) way to write this is:

system *%W(usermod -p #{@options['shadow']} #{@options['username']})

The arguments this way are passed directly into the execve call, so you don't have to worry about sneaky shell tricks.