在PHP中访问CLI程序最安全的方法是什么

时间:2012-11-10 03:28:25

标签: php web-services

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

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

2 个答案:

答案 0 :(得分:2)

我会建议shell_exec()escapeshellcmd()以及escapeshellarg()


澄清(当我第一次发布此答案时,我正忙着):正确的方式 安全 一个shell命令是:

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

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

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

以上代码中的legitimate demo(以及nefarious demo)。

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

注意:通过安全,我的意思是通过转义具有>,{{{{}}等特殊含义的字符,无法执行shell injection attacks 1}},<&&等等(请参阅Wikipedia link),同时正确引用空格和其他可能由shell进行特殊解释的字符。

除此之外,如果您已经将所有允许的命令列入白名单,那么您已经拥有了最好的安全性,并且您不需要上述功能(尽管使用它们并不会有任何损害)。 / p>


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

  • exec():返回命令输出的最后一行,不刷新任何内容。
  • shell_exec():返回命令的整个输出并不刷新任何内容。
  • system():返回命令的最后一行输出,并尝试在输出的每一行之后刷新输出缓冲区。
  • passthru():不返回任何内容并将结果输出传递给浏览器而不会干扰浏览器,尤其在输出为二进制格式时非常有用。

除了system() exit return code之外,您可以使用返回值shell_exec()来模仿所有其他函数的行为。然而,相反,它要么难做,要么就是不可能。

我希望这能为你解决问题。

答案 1 :(得分:1)

理想情况下,您可以使用预先定义的可能输入列表中的passthru()(如果用户input == 'operation_a'您可以{ passthru('operation_a'); }而不必担心清理输入)。否则,请使用passthru()并严格保护输入。 passthru()允许您捕获命令的输出并将整个块传递回浏览器。如果您期望二进制输出(如图像生成和&amp; c。),此功能特别有用。