views:

127

answers:

4

I am taking an input string from a user and using that as the parameters for a command line back-end program.

What is the best way to ensure that this input is "safe"? Aka they haven't inserted "; cd /; rm -rf" or some other ugliness into field?

Without any sanitizing I have...

@query = params[:query]
@result = %x( mycommand #{@query} )

I need to get the output of the command, so I can't use system("command","parameters") as that only returns true or false but would provide protection.

I know this is dangerous... thanks in advance.

+6  A: 

Always, always define what you will accept and then deny everything else. Too often people try to allow everything and then deny the bad things.

  1. Start with characters. I.e. if mycommand only needs alphanumeric input plus spaces then only allow that. There would be no chance of "rm -rf /" sneaking in, nor of the other 10,000 things that require punctuation.
  2. Are there further syntactics/semantics of mycommand that you can use to define "good" input? Such as it requires exactly 2 space separated parameters?

Without knowing what mycommand is I can't offer specifics, but you get the idea: don't try to throw away bad things; define valid and throw away everything else. Note that this is still hard, but without this approach it's almost impossible.

dwc
Ok. I guess I was wondering if there was a standard sanity checker... ala <%=h.I can define the input. It is either a domain name or an IP address. So two regexps can cover those.They will eliminate ;, \n, |, etc. So I will be set. I was just curious if there was a best practice way of "always run this filter" to use as a minimum.
SWR
SWR, there's no magic filter. Using %x with user input is too flexible for that. For domain name or address it would be much better to not use %x and directly call a library routine instead.
dwc
+3  A: 

Due to the nature of executing commands, I would probably say that you should use a whitelist to ensure that only anticipated commands are run. This strikes me as rather dangerous though!

Mr. Matt
+1  A: 

If as you said in your response to dwc, you require a domain name (im assuming you mean fully qualified) or an IP address, you can use Resolv to do a lookup on them and only accept them if there's a matching A/CNAME in the case of a domainname, or a PTR in the case of an IP.

If they enter an IP to which there's no reverse ptr, you could have problems. If they enter a domainname to which there's no A/CNAME, then chances are your command would have failed anyway.

Mike
you can use netaddr to validate IP addresses instead of resolv in the event there is no ptr. also u may wanna verify there's no ruby native way to implement mycommand.
Mike
A: 

Another option, if your commands are bounded, you could create a list in a drop down of commands and put the args into other fields/checkboxes/pulldowns. Then validate each argument as Mike suggests.

This would prevent any user entered value from really making it to the command line.

GreenKiwi