何时使用filter_input()

Jon*_*han 27 php security

这个问题最初是在这里的评论中提出的.

filter_input()仍然是必要的,如果你正在使用参数化查询,并用htmlspecialchars()打印所有用户提供的数据之前?

对我来说似乎没必要,但我总是被告知"过滤输入,逃避输出".因此,除了数据库(或其他形式的存储)之外,是否还需要过滤输入的数据?

Sve*_*sen 30

那么,会有不同的意见.

我的看法是你应该总是使用它(或者filter一般的扩展名).至少有三个原因:

  1. 消毒输入是你应该经常做的事情.由于该功能为您提供了此功能,因此没有理由找到其他方法来消毒输入.由于它是一个扩展,过滤器也将比大多数PHP解决方案更快,更可能更安全,这当然不会受到伤害.唯一的例外是如果您需要更专业的过滤器.即使这样,你也应该使用FILTER_UNSAFE_RAW过滤器来获取值(参见#3).

  2. filter扩展中有很多好东西.它可以节省您编写清理和验证代码的时间.当然,它并不涵盖每一个案例,但足以让您可以更专注于特定的过滤/验证代码.

  3. 在调试/审核代码时,使用该函数非常有用.使用该功能时,您确切知道输入的内容.例如,如果您使用FILTER_SANITIZE_NUMBER_INT过滤器,那么您可以确定输入将是一个数字 - 没有SQL注入,没有HTML或Javascript代码等.另一方面,如果您使用类似的东西,FILTER_UNSAFE_RAW您知道它应该小心对待,并且它很容易引起安全问题.


tox*_*lot 27

正如Sverri M. Olsen所说,对此有不同的看法.

我非常同意滤波器输入,转义输出这一理念.

如果在打印任何用户提供的数据之前使用参数化查询和htmlspecialchars(),仍然需要filter_input()吗?

简短回答: IMO,不是.这没有必要,但在某些情况下可能有用.


filter_input函数有许多有用的过滤器,我确实使用了其中的一些(即FILTER_VALIDATE_EMAIL).的验证过滤器是有用的验证输入.但是,IMO,转换数据的那些只应该用于输出.

有些人鼓励逃避投入.实际上,filter_input手册页上给出的示例似乎也鼓励了这一点.

$search_html = filter_input(INPUT_GET, 'search', FILTER_SANITIZE_SPECIAL_CHARS);
$search_url = filter_input(INPUT_GET, 'search', FILTER_SANITIZE_ENCODED);
Run Code Online (Sandbox Code Playgroud)

唯一的例子是逃避.结合函数名称(filter_ input)似乎表明转换输入是一种很好的做法.转义是必要的,但IMO应该在输出之前完成,而不是在输入之前完成.至少返回值存储在适当命名的变量中.

我强烈不同意逃避输入.我已经遇到过现实情况,过早转换数据是一个问题.

例如,Google Analytics处理输入的方式会导致我的编码&符号(%26)在排除查询参数之前被解码.结果是我的查询参数的统计信息实际上甚至不存在于我的URL中.请参阅关于此问题的问题仍未解决.

您可能还想阅读为什么转义输入是一个坏主意.以下是我同意的一些摘录,以防文章消失[强调原文].

[...] escape-on-input 是错误的 [...]它是一个分层违规 - 它将输出格式问题混合到输入处理中.分层违规会使您的代码更难理解和维护,因为您必须考虑其他层而不是让每个组件和层执行自己的工作.

您默认损坏了数据.该系统现在正在说明数据的来源.

转换输出不仅无法处理多个输出的问题,实际上会使许多输出的数据不正确.

PHP曾经有一个名为魔术引号的功能.这是一个输入逃逸的功能,引起了各种各样的问题.[...]根据Lerdorf的说法,更新的PHP'过滤器'扩展名是"magic_quotes right right".但它仍然受到这里描述的几乎所有问题的困扰.

那么滤波器扩展如何比魔术引号更好(除了它有许多不同的滤波器这一事实)?过滤器导致许多与魔术引号相同的问题.


以下是我使用的编码约定:

  • $ _POST,$ _GET,$ _REQUEST等中的值不应被转义,应始终被视为不安全
  • 值应在写入数据库或存储在$ _SESSION之前验证1
  • 在写入数据库或存储在$ _SESSION之前,应该清除预期为数字或布尔值的值2
  • 相信数据库和$ _SESSION中的数值和布尔值确实是数字或布尔值
  • 在直接用于任何SQL查询之前,字符串值应该是SQL转义的(非字符串值应该被清理2)或使用预准备语句
  • 字符串值在用于HTML输出之前应该进行HTML转义(非字符串值应该被清理2)
  • 字符串值在用于查询字符串之前应进行百分比编码(非字符串值应该被清理2)
  • 使用变量命名约定(例如*_url,*_html,*_sql)来存储转换后的数据

术语

就我的目的而言,这是我定义上面使用的术语的方式.

  1. 验证意味着确认对数据做出的任何假设,例如具有特定格式或具有值的必需字段
  2. 清理意味着确认值完全符合预期(即$ id_num应该只包含数字)

摘要

一般来说(可能有一些例外),我建议如下:

  • 输入上使用验证过滤器
  • 输出上使用清理过滤器
  • 记住TIMTOWDI - 例如,我更喜欢htmlspecialchars()(有更多选项)而不是FILTER_SANITIZE_FULL_SPECIAL_CHARS或FILTER_SANITIZE_SPECIAL_CHARS(它会逃脱换行符)