2

我正在编写一个 PHP 库,它需要访问系统并访问一个没有 PHP 接口(或 PHP 库)的命令行程序。因此,我想知道访问系统以从 CLI 程序中检索输出的最佳(也是最安全的方式)是什么?我已经查看了system()exec(),但仍然不确定在这种情况下哪个最适合使用。

该库将获取一串用户传递的文本,并将其传输到命令行,取回另一串文本。显然,通过将用户提供的数据传递给 CLI,我将进行验证以确保不能传递任何可执行数据。

4

2 回答 2

2

我建议与andshell_exec()一起使用。escapeshellcmd()escapeshellarg()


澄清一下(当我第一次发布这个答案时,我正在旅途中):保护shell 命令的正确方法是:

$exe = 'cat';
$args = array('/etc/passwd');

$args = array_map('escapeshellarg', $args);

$escaped = escapeshellcmd($exe . ' ' . implode(' ', $args));

这是上述代码的合法演示(以及恶意演示)。

当然,以上只是一个虚拟示例。但主要思想是应用escapeshellarg()到每个参数,然后调用escapeshellcmd()整个命令字符串(包括可执行文件的路径和先前转义的参数)。这在任意命令中至关重要。

注意:通过安全,我的意思是通过转义具有特殊含义的字符(如, ,等) (请参阅Wikipedia 链接),同时正确引用空格和其他可能也具有特殊含义的字符,从而无法执行shell 注入攻击由shell解释。><&&|

除此之外,如果您已经将所有允许的命令列入白名单,那么您已经拥有了最好的安全性,并且您不需要上述功能(尽管无论如何使用它们并没有什么坏处)。


关于实际的调用函数,它们几乎都做同样的事情,但有一些怪癖。就个人而言,我更喜欢它,shell_exec()因为它的返回值更加通用(来自此页面):

  • exec():返回命令的最后一行输出并且不刷新任何内容。
  • shell_exec():返回命令的整个输出并且不刷新任何内容。
  • system():返回命令的最后一行输出,并尝试在输出的每一行之后刷新输出缓冲区。
  • passthru(): returns nothing and passes the resulting output without interference to the browser, especially useful when the output is in binary format.

Except from the system() exit return code, you can mimic the behavior of all the other functions with the return value of shell_exec(). However, the inverse it's either harder to do, or just not possible.

I hope this clears things up for you.

于 2012-11-10T08:02:44.827 回答
1

理想情况下,您将使用passthru()预定义的可能输入列表(这样如果用户input == 'operation_a'可以{ passthru('operation_a'); }不用担心清理输入)。否则,使用passthru()一些严重的输入卫生。passthru()允许您捕获命令的输出并将整个块传回浏览器。如果您期望二进制输出(例如来自图像生成等),此功能特别有用。

于 2012-11-10T03:36:05.720 回答