【问题标题】:Why is filter_input() incomplete?为什么 filter_input() 不完整?
【发布时间】:2009-11-27 17:21:09
【问题描述】:

目前,我在基于 PHP 的 CMS 上做了大量工作,并且在使用它的同时,我想将用户输入的所有处理和清理工作转移到一个中心位置。 (目前,这里是 $_REQUEST,那里是 $_GET,等等)。

我非常喜欢 filter_input() 并希望将它用于基本卫生,但我不清楚这个函数是否真的可以用于生产。例如,documentation 为 $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 开发过程的人可以对此有所了解。

【问题讨论】:

  • 并且在 2015 年似乎仍然没有实现 $_SESSION 至少没有检查其他人但我只是再次拿起 php 球,但 filter_var 是一种解决方法。
  • INPUT_SESSIONINPUT_FILES 未实现(尽管$_FILES 呈现多维用例,默认情况下与其他用例不同)。将filter_var_array() 用于$_SESSION。我可能还会注意到,也没有“INPUT_DATABASE”,但你仍然有责任。再次尝试filter_var_array()

标签: php security


【解决方案1】:

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

是的,那将是多么可爱。这是不可能的。这不是文本处理的工作原理。

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

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

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

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

【讨论】:

  • @bobince:我说如果您 1.) 知道脚本中需要什么,并且 2.) 将已清理的变量标记为它们是什么,那么它可以在一定程度上完成。我已经分享了 \\\\\\\\\\\\\\'s 知道你在说什么。 :) 我的主要目标是拥有一个带有一组已定义检查的基本“安全检查点”,而不是从整个代码的数组中提取内容。
  • 一个简单的解释是过滤/清理只是您的数据需要经过的过程的一部分。净化后的数据仍然需要转义。例如您不会将未引用的电子邮件地址粘贴到 SQL 查询中,无论它多么有效。
  • @Ben James:是的,当然。但是我仍然看不出将传入数据拉到一个地方有什么问题,并首先对其进行一些通用检查。假设您有一个重定向到不同 URL 的“from”参数。不管它是如何输出的,你都有一个共同的特点,就是你不希望它指向一个外部 URL。我已阅读@stereofrog 回复中的链接并确认所提出的观点;不过,像这样的检查是我想在输入时检查的,而不是在输出时检查的。也许“卫生”这个词选错了,在这种情况下我道歉。
  • 啊,好吧,我想我对“消毒”这个词以及它通常如何应用于 PHP 有点过分敏感。过滤器函数是一堆不相关的字符串格式化函数,其中一些对验证很有用,但其中一些非常不适合输入阶段。我同意这有点粗糙。尽管如果您可以使用 INPUT_POST|INPUT_GET|INPUT_COOKIE(谁想将 cookie 集中到表单解析中?),则 INPUT_REQUEST 不需要太多,但实现起来似乎微不足道。自从过滤器从 PECL 转移到内置后,似乎没有太大的发展。
  • 我倾向于将 sanitizing 视为删除位,而将 validating 视为检查位。我将上下文之间的 转义 视为转换位。我创建了 Sanitizer(具有输入源的子类)、Validator(具有输入源的子类)、Escaper 和 Cipher 类。一切都不会发生在一个地方,但至少它是模块化的。除了参数化查询,我还提倡使用带有 PDO 的存储过程。数据库中的两个用户权限系统(DEFINER/INVOKER 的东西)也很有意义。
【解决方案2】:

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

解释和进一步讨论

What's the best method for sanitizing user input with PHP?

What else should I be doing to sanitize user input?

【讨论】:

  • 阅读上面我与 bobince 的讨论。
【解决方案3】:

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

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

所以永远不要使用 $_REQUEST。使用适合您的方案的 $_GET、$_POST 或 $_COOKIE。 尽可能严格是一个好习惯,这与 PHP 无关,而是与一般编程有关。

【讨论】:

  • $_REQUEST 的有效点,但他们应该这样说,而不是让它未实现。
猜你喜欢
  • 2010-10-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-11
  • 1970-01-01
  • 2020-03-04
  • 2021-10-01
  • 2022-01-15
相关资源
最近更新 更多