php escapeshellarg 和escapeshellcmd 有什么区别?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1881582/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What's the difference between escapeshellarg and escapeshellcmd?
提问by Rory
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.
PHP 有 2 个密切相关的函数,escapeshellarg()和escapeshellcmd(). 它们似乎都在做类似的事情,即帮助使字符串在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.
我应该使用哪一种?我只是希望能够接受一些用户输入并在其上运行命令,而不是让一切都崩溃。如果 PHP 有一个 exec-type-function 接受一个字符串数组(如 argv),它绕过 shell,我会使用它。类似于 Python 的subprocess.call()功能。
采纳答案by Jay Zeng
From http://ie2.php.net/manual/en/function.escapeshellarg.php
来自http://ie2.php.net/manual/en/function.escapeshellarg.php
escapeshellarg() adds single quotes around a string and quotes/escapes any existing single quotes allowing you to pass a string directly to a shell function and having it be treated as a single safe argument.
escapeshellarg() 在字符串周围添加单引号并引用/转义任何现有的单引号,允许您将字符串直接传递给 shell 函数并将其视为单个安全参数。
escapeshellarg, as its name indicates, is used as passing shell argument(s). For example, you want to list current directory,
顾名思义,escapeshellarg 用作传递 shell 参数。例如,要列出当前目录,
$dir = ".";
system('ls '.escapeshellarg($dir));
escapeshellcmd('ls $dir');
Both do similar things and simply depends on how you handle your logic, do make sure your normalize and validate your input before passing directly to these methods for better security.
两者都做类似的事情,仅取决于您如何处理逻辑,请确保在直接传递给这些方法之前对输入进行规范化和验证以提高安全性。
回答by Adam
Generally, you'll want to use escapeshellarg, making a single argument to a shell command safe. Here's why:
通常,您会希望使用escapeshellarg,使 shell 命令安全的单个参数。原因如下:
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.
因为给定的路径是未经消毒使用的,所以任何命令都可能被运行。我们可以使用这些escapeshell*方法来尝试防止这种情况发生。
First, using escapeshellcmd:
首先,使用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:
现在,使用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, escapeshellcmdmakes sure a string is only one command, while escapeshellargmakes a string safe to use as a single argument to a command.
总而言之,escapeshellcmd确保一个字符串只是一个命令,同时escapeshellarg使一个字符串可以安全地用作命令的单个参数。
回答by CubicleSoft
A simple solution to determine the difference between any two similar-sounding PHP functions is to write a quick command-line script in PHP that outputs the entire possible search space and just show differences (in this case, comparing 256 values):
确定任何两个听起来相似的 PHP 函数之间差异的简单解决方案是在 PHP 中编写一个快速命令行脚本,该脚本输出整个可能的搜索空间并仅显示差异(在这种情况下,比较 256 个值):
<?php
for ($x = 0; $x < 256; $x++)
{
if (chr($x) !== escapeshellcmd(chr($x))) echo $x . " - cmd: " . chr($x) . " != " . escapeshellcmd(chr($x)) . "\n";
}
echo "\n\n";
for ($x = 0; $x < 256; $x++)
{
if (chr($x) !== substr(escapeshellarg(chr($x)), 1, -1)) echo $x . " - arg: " . chr($x) . " != " . substr(escapeshellarg(chr($x)), 1, -1) . "\n";
}
?>
Running the above under PHP 5.6 on the Windows Command Prompt outputs:
在 Windows 命令提示符输出上在 PHP 5.6 下运行上述内容:
0 - cmd: !=
10 - cmd:
!= ^
33 - cmd: ! != ^!
34 - cmd: " != ^"
35 - cmd: # != ^#
36 - cmd: $ != ^$
37 - cmd: % != ^%
38 - cmd: & != ^&
39 - cmd: ' != ^'
40 - cmd: ( != ^(
41 - cmd: ) != ^)
42 - cmd: * != ^*
59 - cmd: ; != ^;
60 - cmd: < != ^<
62 - cmd: > != ^>
63 - cmd: ? != ^?
91 - cmd: [ != ^[
92 - cmd: \ != ^\
93 - cmd: ] != ^]
94 - cmd: ^ != ^^
96 - cmd: ` != ^`
123 - cmd: { != ^{
124 - cmd: | != ^|
125 - cmd: } != ^}
126 - cmd: ~ != ^~
255 - cmd: ? != ^?
0 - arg: !=
33 - arg: ! !=
34 - arg: " !=
37 - arg: % !=
92 - arg: \ != \
Running the same script under PHP 5.5 for Linux outputs:
在 PHP 5.5 下为 Linux 输出运行相同的脚本:
0 - cmd: !=
10 - cmd:
!= \
34 - cmd: " != \"
35 - cmd: # != \#
36 - cmd: $ != $
38 - cmd: & != \&
39 - cmd: ' != \'
40 - cmd: ( != \(
41 - cmd: ) != \)
42 - cmd: * != \*
59 - cmd: ; != \;
60 - cmd: < != \<
62 - cmd: > != \>
63 - cmd: ? != \?
91 - cmd: [ != \[
92 - cmd: \ != \
93 - cmd: ] != \]
94 - cmd: ^ != \^
96 - cmd: ` != \`
123 - cmd: { != \{
124 - cmd: | != \|
125 - cmd: } != \}
126 - cmd: ~ != \~
128 - cmd: !=
...
255 - cmd: ? !=
0 - arg: !=
39 - arg: ' != '\''
128 - arg: !=
...
255 - arg: ? !=
The main difference is that PHP escapeshellcmd() under Windows prefixes characters with a caret ^ instead of a backslash \. The oddities under Linux from chr(128) through chr(255) for both escapeshellcmd() and escapeshellarg() can be explained by the use of invalid UTF-8 code points being dropped, truncated, or misinterpreted.
主要区别在于 Windows 下的 PHP escapeshellcmd() 使用脱字符 ^ 而不是反斜杠 \ 前缀字符。在 Linux 下,从 chr(128) 到 chr(255) 的 escapeshellcmd() 和 escapeshellarg() 的奇怪之处可以通过使用无效的 UTF-8 代码点被删除、截断或误解来解释。
Also of note is that escapeshellarg() escapes far fewer characters and still gets the job done.
另外值得注意的是,escapeshellarg() 转义的字符要少得多,但仍然可以完成工作。
In terms of overall system and application safety and security, you are better off using escapeshellarg() and individually escape each argument that consists of user input.
就整体系统和应用程序的安全性而言,最好使用 escapeshellarg() 并单独转义由用户输入组成的每个参数。
One final example:
最后一个例子:
echo escapeshellarg("something here") . "\n";
echo escapeshellarg("'something here'") . "\n";
echo escapeshellarg("\"something here\"") . "\n";
Windows outputs:
Windows 输出:
"something here"
"'something here'"
" something here "
Linux outputs:
Linux输出:
'something here'
''\''something here'\'''
'"something here"'
PHP escapeshellarg() on Windows surrounds the string with the double-quote " character while Linux uses the single-quote ' character. PHP on Windows completely replaces internal double-quotes with spaces (which could be a problem in some cases). PHP on Linux goes a bit out of its way to escape single-quotes and backslashes \ are escaped \\ on Windows. PHP escapeshellarg() on Windows also replaces ! and % characters with spaces. All platforms replace \0 with spaces.
Windows 上的 PHP escapeshellarg() 用双引号 " 字符将字符串括起来,而 Linux 使用单引号 ' 字符。Windows 上的 PHP 完全用空格替换了内部双引号(在某些情况下这可能是一个问题)。PHP 上在 Windows 上,Linux 对单引号和反斜杠 \ 进行了转义处理,有些不便。Windows 上的 PHP escapeshellarg() 也将 ! 和 % 字符替换为空格。所有平台都将 \0 替换为空格。
Note that behavior is not necessarily consistent between PHP versions and the PHP documentation doesn't always reflect reality. Writing a quick script or reading the source code of PHP are two ways to figure out what's happening behind the scenes.
请注意,PHP 版本之间的行为不一定一致,并且 PHP 文档并不总是反映现实。编写快速脚本或阅读 PHP 的源代码是了解幕后发生的事情的两种方法。
回答by mph
The PHP docs spell out the difference:
PHP 文档说明了区别:
escapeshellcmd:
escapeshellcmd:
Following characters are preceded by a backslash: #&;`|*?~<>^()[]{}$\, \x0A and \xFF. ' and " are escaped only if they are not paired. In Windows, all these characters plus % are replaced by a space instead.
以下字符以反斜杠开头:#&;`|*?~<>^()[]{}$\、\x0A 和 \xFF。' 和 " 只有在它们不配对时才会被转义。在 Windows 中,所有这些字符加上 % 都被替换为空格。
escapeshellarg:
转义符:
adds single quotes around a string and quotes/escapes any existing single quotes allowing you to pass a string directly to a shell function and having it be treated as a single safe argument.
在字符串周围添加单引号并引用/转义任何现有的单引号,允许您将字符串直接传递给 shell 函数并将其视为单个安全参数。
Source:
来源:
http://www.php.net/manual/en/function.escapeshellcmd.phphttp://www.php.net/manual/en/function.escapeshellarg.php
http://www.php.net/manual/en/function.escapeshellcmd.php http://www.php.net/manual/en/function.escapeshellarg.php

