5

在 php 文档页面中escapeshellcmd有一个警告:

escapeshellcmd() 应该用于整个命令字符串,它仍然允许攻击者传递任意数量的参数。对于转义单个参数,应使用 escapeshellarg()。

我要从中理解什么:

  1. 我是否应该总是使用 escapeshellcmd 转义整个命令字符串,包括已经用 escpaeshellarg 转义的参数?
  2. 我是否应该只转义不是参数的命令项(如果你问我,这是唯一合乎逻辑的事情)?
  3. 我是否应该忽略这个可疑的警告,它会对这两个函数如何相互补充产生更多的困惑?

谢谢你,科斯敏

4

3 回答 3

7

简而言之

  • escapeshellarg:用于将参数用单引号括起来,并转义参数中的引号。
  • escapeshellcmd:用于转义shell元字符,即<,>,| ETC

假设你的 php 版本依赖 bash 来执行命令,我们从bash 手册中知道,

将字符括在单引号中会保留引号内每个字符的字面值。单引号之间不能出现单引号,即使前面有反斜杠。

因此,我们可以得出结论,以下创建命令的方式应该足够了:

$c = escapeshellcmd( $cmd ) . ' ' . escapeshellarg( $arg1 );

但是,如果您需要将 $c 传递给以下函数之一,这可能会给您带来问题:exec、system、passthru 等。经验分析表明,这些函数可以评估某些字符。作为一个例子试试这个:

$cmd = 'echo';
$arg = 'TEST\0ING'; // Since we are using single quotes, \0 shouldn't be evaluated as a null byte char
$c = escapeshellcmd( $cmd ) . ' ' . escapeshellarg( $arg1 ); // echo 'TEST\0ING'
exec( $c . ' > output.txt'); // writes TEST without the ING to output.txt

exec 函数将 '\0' 评估为空字节字符,因此 output.txt 将只包含直到 '\0' 的数据。这已经在运行 PHP 5.4.6 的 Ubuntu 上进行了测试。在我看来,这是一个错误,因为数据的字面意思丢失了。因此,在完整字符串上使用 escapeshellcmd 相对更安全,因为它还转义了作为 shell 元字符的反斜杠 '\':

$c = escapeshellcmd( $cmd . ' ' . escapeshellarg( $arg1 ) );
exec( $c . ' > output.txt'); // writes TEST\0ING to output.txt

这种方法的缺点是其他元字符也将被转义,并且必须被传递参数的程序($cmd)转义。

请注意,我们没有在完整的命令字符串上使用 escapeshellcmd。我们省略了“> output.txt”部分,这样“>”就不会被转义。

结论:

  • 尽量避免将字符串作为命令行参数传递。相反,将数据写入文件并从文件中读取。通过这种方式,您可以确保传递的数据保持不变。

  • 如果您绝对需要将字符串作为命令行参数传递,请始终确保它们是字母数字的。

  • 如果您绝对需要将字符串作为命令行参数传递,则对完整字符串使用 escapeshellcmd 相对更安全。

于 2013-03-28T02:57:00.197 回答
2

所以我认为escapeshellcmd可以防止运行多个命令。

escapeshellcmd() 转义字符串中可能用来欺骗 shell 命令执行任意命令的任何字符。

escapeshellarg是确保用户提供的参数只是一个参数。

escapeshellarg() 在字符串周围添加单引号并引用/转义任何现有的单引号,允许您将字符串直接传递给 shell 函数并将其视为单个安全参数。

所以本质上,如果你(你的程序)正在定义命令,你应该只需要escapeshellarg在每个用户提供的参数上使用,但是如果用户指定命令(除非你设置了真正可靠的服务器权限,否则这已经很不确定了)和论据。

免责声明:这只是我对文档的解释。

编辑:

我同意这里的文档非常混乱。我认为警告暗示将其包裹在整个命令中不会阻止用户使用类似这样的参数

actualArg -someEvilFlag

或者

actualArg -someEvilFlag evilFlagArgument
于 2013-03-22T19:16:07.997 回答
1

我会参考什么是 escapeshellarg 和 escapeshellcmd 之间的区别?其中详细介绍了每个进一步的优点。

我想跟进,我会说接受这个用户输入并仅使用 escapshellcmd 将其扔到 shell 可能无论如何都会以糟糕的方式结束。我将专注于清理和输入验证,并将上述功能用作此代码安全过程的“最后一部分”。

于 2013-03-22T19:02:01.917 回答