PHP的新input_filter不读取$ _GET或$ _POST数组

时间:2008-11-18 11:47:44

标签: php security filter-input

在PHP 5.2中添加了一个名为“input_filter”的安全功能,所以不要说:

$name = $_GET['name'];
你现在可以说:

$name = filter_input (INPUT_GET, 'name', FILTER_SANITIZE_STRING);

它会自动清理你的字符串,还有:

  • FILTER_SANITIZE_ENCODED
  • FILTER_SANITIZE_NUMBER_INT
  • FILTER_SANITIZE_EMAIL
  • FILTER_SANITIZE_URL

等。 所以这是一个非常方便的安全功能,我想完全切换到它。

问题是...... 我经常在处理之前操纵$ _GET和$ _POST数组,如下所示:

$ _ GET ['name'] ='(默认名称)';

但似乎filter_input无法访问$ _GET中的更改,因为它读取类型为int(?)的“INPUT_GET”。如果我可以使用filter_input来读取$ _GET,那将是很好的,但是:

$name = filter_input ( $_GET, 'name', FILTER_SANITIZE_STRING );

给我错误:

Warning: filter_input() expects parameter 1 to be long, array given.

任何人都可以想到我能做到的一种方式:

  • 操纵INPUT_GET的来源(不管它是什么),以便我可以在filter_input读取它们之前更改其值
  • 获取filter_input以阅读$_GET

ADDENDUM:


Rich问道:“为什么你要改变阵列,你肯定希望它们是一个输入,而不是你以编程方式插入的东西。”

这是预处理变量的一个非常方便的地方,例如为了:

  • 设置默认值(如果$ _GET ['state'] =''然后$ _GET ['state'] ='AL')
  • 进行手动处理(删除所有空格等)
  • 安全性(其中一些将由filter_input现在完成)

然后我知道当我得到传入变量时,它是安全有效的。当然,我可以将$ _GET数组复制到另一个数组并处理THAT数组,但这只是一个不必要的步骤,因为I $ _GET已经是一个正常运行的数组,所以用这些已经存在的系统数组来做它是有意义的。

6 个答案:

答案 0 :(得分:19)

您可以使用filter_varfilter_var_array

手动强制它再次读取数组
$name = filter_var ( $_GET['name'], FILTER_SANITIZE_STRING );

答案 1 :(得分:6)

在不修改全局数组的情况下执行此操作的便捷方法:

if (!($name = filter_input(INPUT_GET, 'name'))) {
    $name = 'default_value';
}

或使用三元运算符:

$name = ($name = filter_input(INPUT_GET, 'name')) ? $name : 'default_value';

答案 2 :(得分:2)

如果你手动更换阵列,你肯定不需要打扫它吗?你为什么要改变阵列,当然你希望它们是一个输入,而不是你以编程方式插入的东西。

也许更多的代码/上下文会有所帮助。

答案 3 :(得分:2)

正如Jrngs所建议的那样:

跳过编程修改超全局请求变量并定义和使用新的普通变量。

创建新变量不仅比访问和修改关联数组(带字符串索引的数组)中的值更快,它通常也是一种更好的做法。

filter_input 函数的重点是最终删除超全局变量的使用,因为它们是所有PHP脚本中最危险的一点,也是导致安全漏洞的最常见原因(对于XSS和SQL注入)以及错误和混乱,特别是在大型项目中。

例如,$ _GET和$ _REQUEST变量应为同一个键返回相同的值,但是:

.../?var=1
var_dump($_GET['var']); ---> string '1' (length=1)
var_dump($_REQUEST['var']); ---> string '1' (length=1)
$_GET['var'] = 2;
var_dump($_GET['var']); ---> int 2
var_dump($_REQUEST['var']; ---> string '1' (length=1)

更不用说超级全局变量在面向对象的代码中几乎没有任何意义。

因此,如果filter_input函数访问$ _GET / $ _ POST / $ _ REQUEST超全局变量,那么这将完全打败这个函数。你绝对不应该使用建议的 filter_var 功能:

filter_var($_GET['var'],FILTER_SANITIZE_STRING); ---> JUST NO!

创建了 filter_var 函数,以便为非请求变量提供过滤/清理功能,而不是针对这种“黑客”。您正在做的是基本上从 filter_input 函数中获取过滤器,该函数最初是为了提供更好,更安全的访问请求数据,完全绕过函数本身,以非常方式访问请求数据 filter_input 已创建,用于替换并在请求数据上应用 filter_input 提供的过滤器。这是完全错误的。 :)

答案 4 :(得分:1)

INPUT_GET位只是一个识别者(数字)告诉PHP它需要从$ _GET获取值。

如果要在整个数组上使用filter_input,则需要循环遍历它,将每个数组键发送到filter_input,然后将结果放回$ _GET。

编写一个自己进行清理的函数可能同样容易,而且还应该允许你处理数组中的数组(看起来它不像filter_input那样)。 PHP.net文档注释中有几个这样的示例函数,可以执行诸如删除“魔术引号”之类的操作。有关示例,请参阅here

答案 5 :(得分:0)

PHP的新input_filter不会读取$_GET$_POST数组。 如果要覆盖Global(例如$_GET$_POST),请不要使用filter_input。 而是通过手动传递变量来使用filter_var ( $_GET['name'], FILTER_SANITIZE_STRING )