为什么对提交数据(例如 $_GET、$_POST)调用 extract() 是有风险/不好的做法?
我最近正在阅读这个帖子,其中涉及一些最糟糕的问题PHP 实践。 在第二个答案中,有一个关于 extract() 的使用的小型讨论,我只是想知道所有的愤怒是关于什么的。
我个人用它来分割给定的数组,例如 $_GET
或 $_POST
,然后稍后清理变量,因为它们已为我方便地命名。
这是不好的做法吗? 这里有什么风险? 您对使用 extract()
有什么看法?
I was recently reading this thread, on some of the worst PHP practices.
In the second answer there is a mini discussion on the use of extract()
, and im just wondering what all the huff is about.
I personally use it to chop up a given array such as $_GET
or $_POST
where I then sanitize the variables later, as they have been conveniently named for me.
Is this bad practice? What is the risk here? What are your thoughts on the use of extract()
?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(17)
我发现这只是一种不好的做法,因为它可能会导致许多变量,而未来的维护者(或几周后的你自己)不知道它们来自哪里。 考虑这个场景:
$someVariable
从哪里来? 怎么会有人知道呢?我没有看到从变量开始的数组中访问变量的问题,因此您确实需要使用
extract()
提供一个很好的案例for我认为这是值得的。 如果您真的担心输入一些额外的字符,那么就这样做:我认为这里关于它的安全方面的评论有些夸大了。 该函数可以采用第二个参数,实际上可以让您很好地控制新创建的变量,包括不覆盖任何现有变量(
EXTR_SKIP
),仅覆盖现有变量(这样您就可以创建白名单)(EXTR_IF_EXISTS
),或向变量添加前缀 (EXTR_PREFIX_ALL
)。I find that it is only bad practice in that it can lead to a number of variables which future maintainers (or yourself in a few weeks) have no idea where they're coming from. Consider this scenario:
Where did
$someVariable
come from? How can anyone tell?I don't see the problem in accessing the variables from within the array they started in, so you'd really need to present a good case for using
extract()
for me to think it's worth it. If you're really concerned about typing out some extra characters then just do this:I think the comments here on the security aspects of it are overblown somewhat. The function can take a second parameter that actually gives you fairly good control over the newly created variables, including not overwriting any existing variables (
EXTR_SKIP
), ONLY overwriting existing variables (so you can create a whitelist) (EXTR_IF_EXISTS
), or adding prefixes to the variables (EXTR_PREFIX_ALL
).现在来吧。 人们责怪工具而不是用户。
这就像反对
unlink()
因为你可以用它删除文件。extract()
是一个与其他函数一样的函数,请明智且负责任地使用它。 但不要说它本身不好,那只是无知。Come on now. People blame the tool instead of the user.
That's like talking against
unlink()
because you can delete files with it.extract()
is a function like any other, use it wisely and responsibly. But don't claim it's bad per se, that's just ignorant.风险是:不要信任来自用户的数据,提取到当前符号表意味着您的变量可能会被用户提供的内容覆盖。
(一个无意义的例子)
但是现在一个猜测或知道代码的恶意用户调用:
而不是
现在,$systemCall和$i被覆盖,导致你的脚本首先删除你的数据然后挂起。
the risk is: don't trust data from users, and extracting into the current symbol table means, your variables could be overwritten by something the user provides.
(a nonsensical example)
but now a malicious user who guesses or knows the code calls:
instead of
now, $systemCall and $i are overwritten, resulting in your script deleting your data first and hanging then.
没有什么问题。 否则就不会实施。 当您将变量传递(分配)给视图时,许多(MVC)框架都会使用它。 您只需要小心使用它即可。 在将这些数组传递给 extract() 之前对其进行清理,并确保它不会覆盖您的变量。 不要忘记这个函数还接受更多参数!
使用第二个和第三个参数,您可以控制发生碰撞时的行为。 您可以覆盖、跳过或添加前缀。
http://www.php.net/extract
There is nothing wrong with it. Otherwise it wouldnt be implemented. Many (MVC) frameworks use it when you pass (assign) variables to Views. You just need to use it carefully. Sanitize those arrays before passing it to extract() and make sure it does not override your variables. Dont forget that this function also accepts a few more arguments!
Using the second and third arguments you can control the behavior if collision occurs. You can override, skip or add prefix.
http://www.php.net/extract
如果不小心使用,它可能会让与你一起工作的其他人感到困惑,请考虑:
产量:
在混淆中使用会很有用。 但我无法克服“那个 var 从哪里来?” 我遇到的问题。
If not used carefully it can confuse the heck out of others you work with consider:
Yields:
Would be useful to use in an obfuscation. But I can't get over the "Where did that var come from?" problem that I run into.
人们对提取物非常不满,因为它有可能被滥用。 在任何情况下,执行 extract($_POST) 之类的操作都不是一个好主意,即使您知道自己在做什么。 但是,当您执行诸如将变量暴露给视图模板或类似操作之类的操作时,它确实有其用处。 基本上,只有当您非常确定这样做有充分的理由时才使用它,并且如果您想将 $_POST 等疯狂的东西传递给它,则了解如何使用 extract 类型参数。
People get all up-in-arms about extract because it has the potential to be misused. Doing something like extract($_POST) is not a good idea in any case, even if you know what you are doing. However, it does have it's uses when you are doing things like exposing variables to a view template or something similar. Basically, only use it when you are very certain that you have a good reason for doing so, and understand how to use the extract type parameter if you get the idea of passing something crazy like $_POST to it.
我想很多人不推荐使用它的原因是提取
$_GET
和$_POST
(甚至$_REQUEST
)超全局寄存器全局命名空间中的变量与这些数组中的每个键同名,这基本上是模拟 REGISTER_GLOBALS = 1。I guess the reason a lot of people don't recommend using it is that extracting
$_GET
and$_POST
(even$_REQUEST
) superglobals registers variables in the global namespace with the same name as each key within those arrays, which is basically emulating REGISTER_GLOBALS = 1.如果您在函数中提取,变量将仅在该范围内可用。 这经常在视图中使用。 简单的例子:
使用一些替代目录,检查文件是否存在以及定义的变量和方法 - 您几乎复制了 Zend_View。
您还可以在包含后添加 $this->outVariables = get_define_vars(); 来运行具有特定变量的代码,并获取这些结果以与旧的 php 代码一起使用。
If you extract in a function, the variables will only be available in that scope. This is often used in views. Simple example:
With some alternative directories, checks to see if the file exists and defined variables and methods - you've pretty much replicated Zend_View.
You can also add $this->outVariables = get_defined_vars(); after the include to run code with specific variabels and get the result of these for use with old php code.
我会让 PHP 手册 为我说话。
背景:
extract($_REQUEST)
与在 php.ini 中设置register_globals = On
相同I'll let the PHP manual do the talking for me.
Background:
extract($_REQUEST)
is the same as settingregister_globals = On
in php.ini切勿在全局范围内提取($_GET)。 除此之外,它还有它的用途,比如调用一个可能(可能)有很多可选参数的函数。
对于 WordPress 开发人员来说,这应该看起来有点熟悉:
Never extract($_GET) in a global scope. Other than that, it has its uses, like calling a function that could (potentially) have lots of optional arguments.
This should look vaguely familiar to WordPress developers:
只要您以安全的方式使用,提取物就是安全的。 您想要做的是将数组的键过滤为仅您打算使用的键,并且如果您的场景需要它们存在,则可能检查所有这些键是否存在。
或者
Extract is safe as long as you use it in a safe manner. What you want to do is filter the array's keys to only the ones you intend to use and maybe check that all those keys exist if your scenario requires their existence.
or
风险与 register_globals 相同。 您只需篡改请求,攻击者就可以在您的脚本中设置变量。
The risk is the same as with register_globals. You enable the attacker to set variables in your script, simply by tampering with the request.
正如有人在不同的线程中指出的那样, 这是一种更安全的使用 extract 的方法,只允许它提取您指定的变量,而不是数组包含的所有内容。
这具有双重目的,即记录从中产生的变量,因此跟踪变量不会那么困难。
As someone noted in a different thread, here is a safer way to use extract, by only allowing it to extract variables you specify, instead of everything the array contains.
This serves a dual purpose of documenting what variables are coming out of it so tracking back a variable wont be so difficult.
每种方法的使用都可能导致某些情况,从而成为应用程序的故障点。
我个人认为 extract() 不应该用于用户输入(不可预测)和未经清理的数据。
即使 CodeIgniter 核心代码也使用 extract,因此如果数据经过清理和处理良好,使用该方法一定不会有任何坏处。
我在 CodeIgniter 模型中使用了 extract 和 EXTR_IF_EXISTS 开关并限制了变量的数量,它工作得很好。
Every method usage can lead to some conditions where it can be a point of failure for application.
I personally feel that extract() should not be used for user input(that is not predictable) and for data that is not sanitized.
Even CodeIgniter core code uses extract, so there must be no harm in using the method if data is sanitized and handled well.
I have used extract in CodeIgniter models with the EXTR_IF_EXISTS switch and limiting the number of variables, it works pretty well.
请注意,如果您正在处理用户数据(例如请求的结果),
extract()
并不安全,因此最好将此函数与标志EXTR_IF_EXISTS
和EXTR_PREFIX_ALL
。只要使用得当,就可以安全使用
Be aware that
extract()
is not safe if you are working with user data (like results of requests), so it is better to use this function with the flagsEXTR_IF_EXISTS
andEXTR_PREFIX_ALL
.If you use it right, it safe to use
只是稍微阐述一下以前的答案...只要您正确过滤输入(正如其他人所说), extract() 就没有任何问题; 否则你可能会遇到如下巨大的安全问题:
To just expound a little on previous answers... There's nothing wrong with extract() so long as you filter the input correctly (as other's have stated); otherwise you can end up with huge security issues like this:
不再使用 extract() 的另一个很好的理由是 PHP 中有一种使用 HHVM 的势头,它声称使 PHP 速度提高约 10 倍。 Facebook(它的发明者)正在使用它,维基百科也在使用它,据传 WordPress 也在关注它。
HHVM 不允许 extract()
它仍然是 alpha,所以这不是最大的问题
One additional good reason to no longer use extract() is that there is a momentum in PHP to use HHVM which is claiming to make PHP about 10x faster. Facebook (who made it) is using it, Wikipedia is on it, and WordPress is rumored to to be looking at it.
HHVM doesn't allow extract()
It's still kind of alpha, so it's not the largest concern