php - escapeshellcmd警告

标签 php security

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

escapeshellcmd() should be used on the whole command string, and it still allows the attacker to pass arbitrary number of arguments. For escaping a single argument escapeshellarg() should be used instead.

我要从中理解什么:

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

谢谢, 科斯明

最佳答案

简而言之

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

假设您的 php 版本依赖 bash 来执行命令,我们从 bash manual 中得知,

Enclosing characters in single quotes preserves the literal value of each character within the quotes. A single quote may not occur between single quotes, even when preceded by a backslash.

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

$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 相对更安全。

关于php - escapeshellcmd警告,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15577949/

相关文章:

windows - 确定密码有效期

database - 不由发布服务器存储的用户 session key 是否可以被认为是安全的?

security - 禁用 PDF 打印的命令行工具

java - 是否可以编写一个通过 JDBC 连接到 Oracle 的小程序?

php - 使用隐藏表单将 javascript 变量传输到 php?

php - pecl - gearman - 无法加载动态库?

PhpMyAdmin 删除\n(新行)

php - 将 print_r 结果放入变量中

php - 在 mysql 数据库中存储非拉丁字符时出现问题

javascript - 为什么服务器不应该使用 JSON 数组进行响应?