Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the difference between escapeshellarg and escapeshellcmd?

PHP has 2 closely related functions, escapeshellarg() and escapeshellcmd(). They both seem to do similar things, namely help make a string safer to use in system()/exec()/etc.

Which one should I use? I just want to be able to take some user input and run a command on it, and not have everything blow up. If PHP had an exec-type-function that took an array of strings (like argv), which bypasses the shell, I'd use that. Similar to Python's subprocess.call() function.

like image 788
Amandasaurus Avatar asked Dec 10 '09 15:12

Amandasaurus


People also ask

What does escapeshellcmd do?

escapeshellcmd() escapes any characters in a string that might be used to trick a shell command into executing arbitrary commands. This function should be used to make sure that any data coming from user input is escaped before this data is passed to the exec() or system() functions, or to the backtick operator.

What is Shell_exec?

The shell_exec() function is an inbuilt function in PHP which is used to execute the commands via shell and return the complete output as a string. The shell_exec is an alias for the backtick operator, for those used to *nix. If the command fails return NULL and the values are not reliable for error checking.


1 Answers

Generally, you'll want to use escapeshellarg, making a single argument to a shell command safe. Here's why:

Suppose you need to get a list of files in a directory. You come up with the following:

$path  = 'path/to/directory'; // From user input  $files = shell_exec('ls '.$path); // Executes `ls path/to/directory` 

(This is a bad way of doing this, but for illustration bear with me)

This works "great" for this path, but suppose the path given was something more dangerous:

$path  = 'path; rm -rf /';  $files = shell_exec('ls '.$path); // Executes `ls path`, then `rm -rf /`; 

Because the path given was used unsanitised, any command can potentially be run. We can use the escapeshell* methods to try to prevent this.

First, using escapeshellcmd:

$path = 'path; rm -rf /';  $files = shell_exec(escapeshellcmd('ls '.$path)); // Executes `ls path\; rm -rf /`; 

This method only escapes characters that could lead to running multiple commands, so while it stops the major security risk, it can still lead to multiple parameters being passed in.

Now, using escapeshellarg:

$path = 'path; rm -rf /';  $files = shell_exec('ls '.escapeshellarg($path)); // Executes `ls 'path; rm -rf /'`; 

That gives us the result we want. You'll notice it's quoted the entire argument, so individual spaces, etc, do not need to be escaped. If the argument were to have quotes itself, they would be quoted.

To summarise, escapeshellcmd makes sure a string is only one command, while escapeshellarg makes a string safe to use as a single argument to a command.

like image 128
Adam Avatar answered Oct 07 '22 02:10

Adam