escapeshellcmd警告

Int*_*tor 5 php security

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

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

我从中可以理解的是:

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

谢谢你,Cosmin

man*_*ark 6

简而言之

  • escapeshellarg:用于用单引号括起一个参数,它会转义参数中的引号.
  • escapeshellcmd:用于转义shell元字符,即<,>,| 等等

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

用单引号括起字符可以保留引号中每个字符的字面值.单引号之间可能不会出现单引号,即使前面有反斜杠也是如此.

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

$c = escapeshellcmd( $cmd ) . ' ' . escapeshellarg( $arg1 );
Run Code Online (Sandbox Code Playgroud)

但是,如果您需要将$ 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
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

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

请注意,我们没有在完整的命令字符串上使用escapeshellcmd.我们省略了'> output.txt'部分,以便'>'不会被转义.

结论:

  • 尽量避免将字符串作为命令行参数传递.而是将数据写入文件并从文件中读取.这样,您可以确保传递的数据保持不变.

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

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