PHP - 是否需要在'putenv'调用中转义$ setting?

时间:2018-05-22 13:16:35

标签: php escaping environment-variables

putenv函数只接受一个参数,一个字符串。该字符串应采用以下格式:KEY=VALUE

参考:http://php.net/manual/en/function.putenv.php

将以下代码作为潜在用例:

if(getenv(ON_SOME_ENVIRONMENT)) {

  // What happens if $dir contains an '=' character?
  $dir = dirname(__FILE__);

  putenv('SOME_KEY=' . $dir);
}

以上示例中的$dir是否需要转义?如果是这样,需要进行什么样的逃避?

3 个答案:

答案 0 :(得分:2)

我不确定正确的答案,但我希望这会有所帮助。

一般来说,过滤用户输入取决于使用输入的上下文以及该上下文中的控制字符是什么。似乎 = 是一个控制字符,您希望避免将其解释为控制字符,因此过滤是一回事。如果有一个合适的语言内置函数可以用来进行过滤,它是该上下文的正确函数,那么您应该使用该函数。例如,我猜你知道,在将用户输入传递给 exec() 之前,escapeshellarg 是用于 shell 参数的正确方法。在调用 putenv 之前,我没有看到要使用的类似函数。如果您可以根据通常更强大的许可名单方法制作过滤器。例如,在大多数情况下,只允许从 a-z 使用 ASCII 字母将是允许英文名称而不让控制字符潜入的好方法。

防止恶意输入的另一种策略是使用许可名单方法而不是(或除了)过滤方法。因此,如果您知道接受的输入是 ASCENDINGDESCENDING,那么不要向用户提供文本框,而是给他们一个下拉列表,并确保他们选择了 ASCENDINGDESCENDINGputenv 函数中使用它之前(ASCENDING 和 DESCENDING 是可能预期的随机示例,但请根据您的情况进行调整)。当然,如果用户输入可以是各种各样的东西,这将不起作用。

一些实际测试:

某些行为似乎与版本和/或平台有关。

在 MacOS 上使用 PHP 7.3 时,我得到了与 @michfuer 相同的结果。

在运行 Linux 5.10.25-linuxkit 和 PHP 7.4 的 ddev docker 容器上做同样的测试,我得到了不同的结果:

$ php -a
Interactive mode enabled
php > putenv('SOME_KEY=foo/bar=baz');
php > var_dump(getenv('SOME_KEY'));         // value "foo/bar=baz"
string(11) "foo/bar=baz"
php > var_dump(getenv('SOME_KEY='));        // value "foo/bar=baz"
bool(false)
php > var_dump(getenv('SOME_KEY=foo'));     // value "foo/bar=baz"
bool(false)
php > var_dump(getenv('SOME_KEY=foo/bar')); // value "foo/bar=baz"
string(3) "baz"
php > var_dump(getenv('SOME_KEY=blarg'));   // value "foo/bar=baz"
bool(false)
php > var_dump(getenv('SOME'));             // value false
bool(false)

答案 1 :(得分:2)

看起来php putenv() 是包装了同名的C 库函数 https://github.com/php/php-src/blob/master/ext/standard/basic_functions.c#L894

环境变量value可以包含=,但name不能,见

在 PHP 7.3 上本地测试 (macOS)

putenv('SOME_KEY=foo/bar=baz');
var_dump(getenv('SOME_KEY'));         // value "foo/bar=baz"
var_dump(getenv('SOME_KEY='));        // value "foo/bar=baz"
var_dump(getenv('SOME_KEY=foo'));     // value "foo/bar=baz"
var_dump(getenv('SOME_KEY=foo/bar')); // value "foo/bar=baz"
var_dump(getenv('SOME_KEY=blarg'));   // value "foo/bar=baz"
var_dump(getenv('SOME'));             // value false

getenv() 忽略 = 字符串我认为是有道理的,因为这是名称的受限字符。

所以我认为 $dir 不需要任何特殊的转义。

答案 2 :(得分:-3)

<?php 
$dir = dirname(__FILE__);
putenv("ABC=$dir");

echo getenv('ABC');

输出:

d:\项目\演示