This post details what a Command Injection vulnerabilitiy is, why you need to fix them, and how to fix them!
What is a Command Injection Vulnerability?
Command Injection is one of the worst types of security vulnerabilities that you can have within your system. It’s one part of a larger umbrella of vulnerabilities known as Injection vulnerabilities. Injection vulnerabilities have taken the #1 spot on the OWASP Top 10 in both 2010 and 2013.
*Using my best John Oliver voice*: Not something to be proud of Injection!
Command Injection looks like this:
That’s all that is required for an attacker to gain full access to your system. In such a case all of your data could be stolen, modified, or deleted. Not code that you want to be responsible for writing!
So how does an attacker leverage this code? Since the user is able to provide
could do this:
1 2 3 4
This gives the attacker full access to the details of your database. At this point, your company goes bankrupt, you lose your job, and you stub your toe on the way out of your office. It’s a terrible day!
Let’s fix it.
How to Fix Command Injection Vulnerabilities in Rails/Ruby
There are multiple formats that a Command Injection vulnerability can come in based upon the system call that you’re making. Here’s some examples:
1 2 3 4 5 6 7 8 9 10 11
There are tons of commands that you could be using and thankfully they all follow the same pattern for properly protecting them from Command Injection.
To safely protect from Command Injection, call your command by breaking each piece into a seperate string. Here’s an example:
1 2 3 4
That’s it. Really simple! Now there are a few special cases that you’re going to run into, so let’s look at those.
Backtick (`) method
The backtick method is handled in a different way when writing system commands. Namely you cannot provide
it multiple arguments. So instead when faced with command injection for backtick, you’ll need to use another
1 2 3 4
Output redirection is another special cases. Let’s say you’ve got a command like this:
Simple enough you think, and you change the backtick method to
The problem is you’re going to run into an error like this:
ls 2>&1: No such file or directory
This is because the system command now thinks that
2>&1 is a part of the arguments to
ls and not
an output redirection.
To fix this, you’re going to have to use a command from the
library to properly handle output redirection. Because you’re using
2>&1 – which means redirecting
stdout – you’re going to use
And don’t forget to
require 'open3' otherwise you’ll get:
NameError: uninitialized constant Open3
One pattern that I’ve seen is logging before running a system command like so:
1 2 3
I like to use the
operator to simplfy the above to:
1 2 3
File Access Vulnerabilities
One big caveat with all of the above is that there is still potential for abuse. Let’s say you’ve got the following command:
The above is a type of File Access vulnerability and brakeman isn’t going to recognize it!
In this case you’d want to switch to a Ruby built in command like
File.read to grab the contents of the file, and make sure to sanitize the payload. Just remember to be
careful that you don’t create a new vulnerability when fixing an old one!