17

I'm coding a web interface to a horrible piece of propitiatory software our company uses. The software has no real UI and requires us giving putty access to our system for our clients to even pull data. My web interface has to run an exec(); function and it has to pass a few variables the user inputs.

$command = "report-call '$type' '$study' '$server' '$tag' '$specopt1' '$specopt2' '$specopt3' '$specopt4'";
$last_line = exec($command, $output, $returnvalue); 

Now I assume I might be able to just remove any semicolons from the $command varible and be safe, but I'm not sure and that's why I'm posing this here before we go live next month.

What would be the best way to sanitize $command? There are a few special chars that I do need to be in the variables [ ] < > ! # $ .

The Digital Ninja
  • 1,090
  • 6
  • 22
  • 36

1 Answers1

25

Use the function that PHP has for this purpose:

$cmd = 
     "/usr/bin/do-something " . 
     escapeshellarg($arg1) . 
     ' ' . 
     escapeshellarg($arg2);

You can also use escapeshellcmd()

What's the difference?

escapeshellarg() ONLY adds ' around the string and then \ before any other ' characters. http://www.php.net/escapeshellarg

escapeshellcmd() escapes all shell-sensitive characters ($, \, etc..) but does not add quotes. http://www.php.net/manual/en/function.escapeshellcmd.php

The gotcha is in the case that you use escapeshellarg() as PART OF A QUOTED parameter. Then it is rendered useless (actually adding quotes to the mix).

Generally speaking, we prefer to use escapeshellcmd() with our own quotes added.

$cmd = 
    "/usr/bin/do-something '" . 
    escapeshellcmd($arg1) . 
    "' '" . 
    escapeshellcmd($arg2) . 
    "'";

Be safe!

gahooa
  • 131,293
  • 12
  • 98
  • 101
  • 5
    Deleted my answer because apparently we were typing at the same time, but you gave decent examples. Links to manual: http://us.php.net/manual/en/function.escapeshellarg.php, http://us.php.net/manual/en/function.escapeshellcmd.php – anonymous coward Jun 11 '09 at 19:06
  • 3
    Just a note that `escapeshellcmd()` does not actually escape '!', so if you're running the command in e.g. Bash, you're still vulnerable to command replacement (e.g. `this-is-a-test-!467` where `!467` will be replaced by whatever is no. 467 in your shell history). `escapeshellarg()` alleviates that. – madsen Aug 24 '17 at 09:35
  • This was hugely helpful and I had never heard of these commands. Thank you very much. – Andy Borgmann Sep 23 '20 at 14:58