为什么 filter_input() 不完整?

Why is filter_input() incomplete?

提问人:Pekka 提问时间:11/28/2009 更新时间:11/28/2009 访问量:7062

问:

我目前正在开发一个基于PHP的CMS,当我在做这件事时,我想把用户输入的所有处理和清理工作转移到一个中心位置。(目前,这里是 _REQUEST 美元,那里是 _GET 美元,依此类推)。

我非常喜欢 filter_input(),并希望将其用于基本的卫生设施,但我不清楚此功能是否真的可用于生产。例如,文档将以下参数命名为 $type

INPUT_GET, INPUT_POST, INPUT_COOKIE, INPUT_SERVER, INPUT_ENV, INPUT_SESSION (not implemented yet) and INPUT_REQUEST (not implemented yet).

该函数自 5.2.0 以来就存在,为什么两个关键元素尚未实现?如果我想从 $_REQUEST 获取数据,您必须使用用户贡献的注释中的解决方法。这有什么特殊原因吗?这个功能还在某种测试版中吗?作为处理传入数据的第一个调用是否值得信赖?

也许熟悉PHP开发过程的人可以对此有所了解。

PHP 安全

评论

1赞 CodingInTheUK 3/22/2015
在 2015 年,似乎仍然没有实现 _SESSION 美元,至少没有检查其他人,我只是再次拿起 php 球,但filter_var是一种解决方法。
2赞 Anthony Rutledge 10/21/2015
INPUT_SESSION并且没有实现(尽管呈现了一个多维用例,并且默认情况下与其他用例不同)。用于 .我可能还会注意到,也没有“INPUT_DATABASE”,但你仍然有责任。再次尝试.INPUT_FILES$_FILESfilter_var_array()$_SESSIONfilter_var_array()

答:

3赞 Flavius 11/28/2009 #1

在编程中,您必须尽可能限制您的输入。这也适用于数据源。_REQUEST 美元包含 _GET 美元、_POST 美元和 _COOKIE 美元中的所有内容,这可能会导致问题。

例如,如果CMS的插件在其中一个插件中引入了一个新的特殊密钥,而该密钥恰好作为另一个插件中的有意义的密钥存在,会发生什么?

所以永远不要使用 _REQUEST 美元。使用 _GET 美元、_POST 美元或 _COOKIE 美元,以适合您的情况为准。 尽可能严格是一种很好的做法,这与PHP无关,但与一般的编程有关。

评论

1赞 Pekka 11/28/2009
_REQUEST 美元的有效点,但随后他们应该这么说,而不是让它不实施。
8赞 bobince 11/28/2009 #2

我想将用户输入的所有处理和卫生工作转移到一个中心位置

是的,那该有多可爱。这是做不到的。这不是文本处理的工作方式。

如果要将文本从一个上下文插入到另一个上下文中,则需要使用正确的转义符。(mysql_real_escape_string用于MySQL字符串文字,htmlspecialchars用于HTML内容,urlencode用于URL参数,其他用于特定上下文)。在脚本开始时,当你进行筛选时,你不知道你的输入将在哪里结束,所以你不知道如何转义它。

也许一个输入字符串既进入数据库(需要 SQL 转义)又直接进入页面(需要 HTML 转义)。没有一种逃脱可以涵盖这两种情况。您可以一个接一个地使用这两个转义符,但是 HTML 中的值将出现奇怪的反斜杠,并且数据库中的副本将充满与号。这种错误编码的几轮,你会遇到这样的情况,每次你编辑一些东西时,都会出现一长串。\\\\\\\\\\\\\\\\\\\\&

在开始时,您可以一次性安全地进行过滤的唯一方法是完全删除所有需要在您将要使用它们的上下文中转义的字符。但这意味着你的HTML中没有撇号或反斜杠,你的数据库中没有与号或小于号,而且可能还必须去掉一大堆其他对URL不友好的标点符号。对于一个不采用任意文本的简单网站,您也许可以侥幸逃脱。但通常不会。

因此,只有当一种类型的文本进入另一种类型的文本时,您才能即时逃脱。避免此问题的最佳策略是尽可能避免将文本连接到其他上下文中,例如,使用参数化查询而不是 SQL 字符串生成,并使用漂亮的短名称定义函数以减少键入的工作量,或者使用默认情况下 HTML 转义的替代模板系统。echo(htmlspecialchars())

评论

0赞 Pekka 11/28/2009
@bobince:我说,如果你 1.)了解脚本中需要什么,以及 2.)将清理后的变量标记为它们是什么。我有我的\\\\\\\\\\\\\\知道你在说什么。:)我的主要目标是有一个基本的“安全检查点”,其中包含一组定义的检查,而不是从整个代码的数组中提取内容。
0赞 Ben James 11/28/2009
一个简单的解释是,过滤/清理只是数据需要经历的过程的一部分。清理后的数据仍需要转义。例如,无论它的有效性如何,您都不会将未加引号的电子邮件地址粘贴到 SQL 查询中。
0赞 Pekka 11/28/2009
@Ben James:是的,当然。但是我仍然看不出将传入数据拉到一个地方有什么问题,并首先对其运行一些通用检查。假设您有一个重定向到其他 URL 的“from”参数。无论它如何输出,您都有一个共同特征,即您不希望它指向外部 URL。我已阅读@stereofrog回复中的链接并承认所提出的观点;不过,像这样的检查是我想在输入时检查的,而不是在输出时检查的。也许“卫生”这个词选择错了,在这种情况下,我深表歉意。
1赞 bobince 12/2/2009
啊,好吧,我想我对“清理”这个词以及它通常如何应用于 PHP 有点过于敏感了。filter 函数是一堆不相关的字符串格式化函数,其中一些对验证很有用,但有些则不适合输入阶段。我同意这有点粗糙。虽然如果你能使用INPUT_REQUEST INPUT_POST|INPUT_GET|INPUT_COOKIE(谁想把 cookie 归为形式 pars?),这似乎是微不足道的。自从过滤器从 PECL 转移到内置以来,似乎没有太多的发展。
1赞 Anthony Rutledge 10/21/2015
我倾向于将清理视为删除位,而验证则视为检查位。我认为在上下文之间转义是转换位。我创建了 Sanitizer(按输入源提供子类)、Validator(按输入源提供子类)、Escaper 和 Cipher 类。一切都不会发生在一个地方,但至少它是模块化的。除了参数化查询之外,我还主张将存储过程与 PDO 一起使用。数据库中的双用户权限系统(DEFINER/INVOKER 东西)也很有意义。
4赞 user187291 11/28/2009 #3

“输入过滤”或“卫生”是一个荒谬的想法。远离它。

解释和进一步讨论

使用 PHP 清理用户输入的最佳方法是什么?

我还应该做些什么来清理用户输入?

评论

0赞 Pekka 12/1/2009
阅读我上面与 bobince 的讨论。