一般来说,您会想要使用escapeshellarg http://www.php.net/manual/en/function.escapeshellarg.php,使 shell 命令的单个参数变得安全。原因如下:
假设您需要获取目录中的文件列表。你得出以下结论:
$path = 'path/to/directory'; // From user input
$files = shell_exec('ls '.$path);
// Executes `ls path/to/directory`
(这是一个不好的方法,但为了便于说明,请耐心等待)
这对于这条路径“非常好”,但假设给定的路径更危险:
$path = 'path; rm -rf /';
$files = shell_exec('ls '.$path);
// Executes `ls path`, then `rm -rf /`;
由于给定的路径未经过滤使用,因此任何命令都可能运行。我们可以使用escapeshell*
尝试防止这种情况发生的方法。
首先,使用escapeshellcmd http://www.php.net/manual/en/function.escapeshellcmd.php:
$path = 'path; rm -rf /';
$files = shell_exec(escapeshellcmd('ls '.$path));
// Executes `ls path\; rm -rf /`;
此方法仅转义可能导致运行多个命令的字符,因此虽然它阻止了主要的安全风险,但仍然可能导致传入多个参数。
现在,使用escapeshellarg http://www.php.net/manual/en/function.escapeshellarg.php:
$path = 'path; rm -rf /';
$files = shell_exec('ls '.escapeshellarg($path));
// Executes `ls 'path; rm -rf /'`;
这给了我们我们想要的结果。您会注意到它引用了整个参数,因此不需要转义单独的空格等。如果论证本身有引号,它们就会被引用。
总而言之,escapeshellcmd
确保字符串只是一个命令,而escapeshellarg
使字符串可以安全地用作命令的单个参数。