php 使用 $_REQUEST[] 有什么问题?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2142497/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 05:13:33  来源:igfitidea点击:

What's wrong with using $_REQUEST[]?

phpmethodsform-submit

提问by sprugman

I've seen a number of posts on here saying not to use the $_REQUESTvariable. I usually don't, but sometimes it's convenient. What's wrong with it?

我在这里看到很多帖子都说不要使用$_REQUEST变量。我通常不这样做,但有时很方便。它出什么问题了?

回答by bobince

There's absolutely nothing wrong with taking input from both $_GETand $_POSTin a combined way. In fact that's what you almost always want to do:

从两者$_GET$_POST结合的方式获取输入绝对没有错。事实上,这就是你几乎总是想做的事情:

  • for a plain idempotent request usually submitted via GET, there's the possibility the amount of data you want won't fit in a URL so it has be mutated to a POST request instead as a practical matter.

  • for a request that has a real effect, you have to check that it's submitted by the POST method. But the way to do that is to check $_SERVER['REQUEST_METHOD']explicitly, not rely on $_POSTbeing empty for a GET. And anyway if the method is POST, you still might want to take some query parameters out of the URL.

  • 对于通常通过 GET 提交的普通幂等请求,您想要的数据量可能无法放入 URL,因此实际上它已被更改为 POST 请求。

  • 对于具有实际效果的请求,您必须检查它是否由 POST 方法提交。但是这样做的方法是$_SERVER['REQUEST_METHOD']明确检查,而不是依赖于$_POST为空来获取 GET。无论如何,如果方法是POST,您仍然可能希望从 URL 中取出一些查询参数。

No, the problem with $_REQUESTis nothing to do with conflating GET and POST parameters. It's that it also, by default, includes $_COOKIE. And cookies really aren't like form submission parameters at all: you almost never want to treat them as the same thing.

不,问题与$_REQUEST合并 GET 和 POST 参数无关。默认情况下,它还包含$_COOKIE. 并且 cookie 真的根本不像表单提交参数:您几乎从不想将它们视为相同的东西。

If you accidentally get a cookie set on your site with the same name as one of your form parameters, then the forms that rely on that parameter will mysteriously stop working properly due to cookie values overriding the expected parameters. This is very easy to do if you have multiple apps on the same site, and can be very hard to debug when you have just a couple of users with old cookies you don't use any more hanging around and breaking the forms in ways no-one else can reproduce.

如果您不小心在您的站点上设置了一个与表单参数同名的 cookie,那么依赖该参数的表单将由于 cookie 值覆盖预期参数而神秘地停止正常工作。如果您在同一个站点上有多个应用程序,这很容易做到,并且当您只有几个使用旧 cookie 的用户时可能很难调试,您不再使用任何更多的闲逛和破坏表单的方式没有- 其他人可以复制。

You can change this behaviour to the much more sensible GP(no C) order with the request_orderconfig in PHP 5.3. Where this is not possible, I personally would avoid $_REQUESTand, if I needed a combined GET+POST array, create it manually.

您可以使用PHP 5.3 中的request_order配置将此行为更改为更合理的GP(无C)顺序。如果这是不可能的,我个人会避免,如果我需要组合的 GET+POST 数组,请手动创建它。$_REQUEST

回答by Gordon

I've been digging through some newsgroup posts on PHP Internalsand found an interesting discussion about the topic. The initial thread was about something else, but a remark by Stefan Esser, a (if not the) security expert in the PHP world turned the discussion towards the security implications of using $_REQUEST for a few posts.

我一直在挖掘有关PHP Internals 的一些新闻组帖子,并发现了有关该主题的有趣讨论。初始线程是别的事情,但此话出自Stefan Esser,如果一个(如果不是在PHP世界)的安全专家转向使用$ _REQUEST几个职位的安全性问题的讨论。

Citing Stefan Esser on PHP Internals

在 PHP Internals 上引用Stefan Esser

$_REQUEST is one of the biggest design weaknesses in PHP. Every application using $_REQUEST is most probably vulnerable to Delayed Cross Site Request Forgery problems. (This basically means if e.g. a cookie named (age) exists it will always overwrite the GET/POST content and therefore unwanted requests will be performed)

$_REQUEST 是 PHP 中最大的设计弱点之一。每个使用 $_REQUEST 的应用程序很可能容易受到延迟跨站点请求伪造问题的影响。(这基本上意味着,如果一个名为 (age) 的 cookie 存在,它将始终覆盖 GET/POST 内容,因此将执行不需要的请求)

and in a later reply to the same thread

并在稍后回复同一线程

It is not about the fact that someone can forge GET, POST; COOKIE variables. It is about the fact that COOKIEs will overwrite GET and POST data in REQUEST.

Therefore I could infect your browser with a cookie that says e.g. action=logout and from that day on you cannot use the application anymore because REQUEST[action] will be logout forever (until you manually delete the cookie).

And to infect you with a COOKIE is so simple...
a) I could use an XSS vuln in any application on a subdomain
b) Ever tried setting a cookie for *.co.uk or *.co.kr when you own a single domain there?
c) Other cross domain whatever ways...

And if you believe that this is not an issue then I can tell you that there is a simple possibility to set f.e. a *.co.kr cookie that results in several PHP versions just returning white pages. Imagine: Just a single cookie to kill all PHP pages in *.co.kr

And by setting an illegal session ID in a cookie valid for *.co.kr in a variable called +PHPSESSID=illegalyou can still DOS every PHP application in korea using PHP sessions...

这不是关于某人可以伪造 GET、POST 的事实;COOKIE 变量。这是关于 COOKIE 将覆盖 REQUEST 中的 GET 和 POST 数据的事实。

因此,我可以用一个 cookie 感染您的浏览器,该 cookie 表示例如 action=logout,从那天起您不能再使用该应用程序,因为 REQUEST[action] 将永远注销(直到您手动删除 cookie)。

用 COOKIE 感染你是如此简单......
a) 我可以在子域上的任何应用程序中使用 XSS 漏洞
b) 当你拥有一个 cookie 时,曾经尝试为 *.co.uk 或 *.co.kr 设置单域有吗?
c) 其他任何方式的跨域...

如果您认为这不是问题,那么我可以告诉您,有一种简单的可能性可以设置 fe *.co.kr cookie,这会导致多个 PHP 版本仅返回白页。想象一下:只需一个 cookie 即可杀死 *.co.kr 中的所有 PHP 页面

通过在一个对 *.co.kr 有效的 cookie 中设置一个非法会话 ID,在一个名为 +PHPSESSID=非法的变量中,您仍然可以使用 PHP 会话在韩国对每个 PHP 应用程序进行 DOS...

The discussion continues for a few more postings and is interesting to read.

讨论继续进行了更多的帖子,阅读起来很有趣。



As you can see, the main problem with $_REQUEST is not so much that it has data from $_GET and $_POST, but also from $_COOKIE. Some other guys on the list suggested changing the order in which $_REQUEST is filled, e.g. filling it with $_COOKIE first, but this could lead to numerous other potential problems, for instance with Session handling.

如您所见,$_REQUEST 的主要问题不在于它包含来自 $_GET 和 $_POST 的数据,还包含来自 $_COOKIE 的数据。列表中的其他一些人建议更改填充 $_REQUEST 的顺序,例如先用 $_COOKIE 填充它,但这可能会导致许多其他潜在问题,例如 Session processing

You could completely omit $_COOKIES from the $_REQUEST global though, so that it is not overwritten by any of the other arrays (in fact, you can limit it to any combination of it's standard contents, like the PHP manual on the variable_orderini settingtells us:

但是,您可以从 $_REQUEST 全局中完全省略 $_COOKIES,这样它就不会被任何其他数组覆盖(实际上,您可以将其限制为标准内容的任意组合,例如有关variable_orderini 设置PHP 手册告诉我们:

variable_order Sets the order of the EGPCS (Environment, Get, Post, Cookie, and Server) variable parsing. For example, if variables_order is set to "SP" then PHP will create the superglobals $_SERVER and $_POST, but not create $_ENV, $_GET, and $_COOKIE. Setting to "" means no superglobals will be set.

variable_order 设置 EGPCS(Environment、Get、Post、Cookie 和 Server)变量解析的顺序。例如,如果 variables_order 设置为“SP”,那么 PHP 将创建超级全局变量 $_SERVER 和 $_POST,但不会创建 $_ENV、$_GET 和 $_COOKIE。设置为 "" 意味着不会设置超全局变量。

But then again, you might also consider not using $_REQUEST altogether, simply because in PHP you can access Environment, Get, Post, Cookie, and Server in their own globals and have one attack vector less. You still have to sanitize this data, but it's one less thing to worry about.

但话又说回来,您也可以考虑不完全使用 $_REQUEST,因为在 PHP 中,您可以在自己的全局变量中访问 Environment、Get、Post、Cookie 和 Server,并且减少了一个攻击向量。您仍然需要清理这些数据,但不必担心这一点。



Now you might wonder, why does $_REQUEST exists after all and why it is not removed. This was asked on PHP Internals as well. Citing Rasmus Lerdorf about Why does $_REQUEST exist?on PHP Internals

现在您可能想知道,为什么 $_REQUEST 到底存在以及为什么它没有被删除。这也在 PHP Internals 上被问到。引用 Rasmus Lerdorf 关于为什么 $_REQUEST 存在?在 PHP 内部

The more stuff like this we remove, the harder it becomes for people to quickly move to newer, faster and more secure versions of PHP. That causes way more frustration for everyone than a few "ugly" legacy features. If there is a decent technical reason, performance or security, then we need to take a hard look at it. In this case, the thing we should be looking at isn't whether we should remove $_REQUEST but whether we should remove cookie data from it. Many configurations already do that, including all of my own, and there is a strong valid security reason for not including cookies in $_REQUEST. Most people use $_REQUEST to mean GET or POST, not realizing that it could also contain cookies and as such bad guys could potentially do some cookie injection tricks and break naive applications.

我们删除的此类内容越多,人们就越难快速迁移到更新、更快和更安全的 PHP 版本。与一些“丑陋”的遗留功能相比,这给每个人带来了更多的挫败感。如果有一个不错的技术原因、性能或安全性,那么我们需要仔细研究一下。在这种情况下,我们应该关注的不是我们是否应该删除 $_REQUEST 而是我们是否应该从中删除 cookie 数据。许多配置已经这样做了,包括我自己的所有配置,并且在 $_REQUEST 中不包含 cookie 有一个强有力的有效安全理由。大多数人使用 $_REQUEST 表示 GET 或 POST,没有意识到它也可能包含 cookie,因此坏人可能会做一些 cookie 注入技巧并破坏幼稚的应用程序。

Anyway, hope that shed some light.

无论如何,希望能有所启发。

回答by Luca Matteis

$_REQUESTrefers to all sorts of requests (GET, POST etc..). This is sometimes useful, but is usually better to specify the exact method ($_GET, $_POST etc).

$_REQUEST指各种请求(GET、POST 等)。这有时很有用,但通常最好指定确切的方法($_GET、$_POST 等)。

回答by Ben James

GET requests should be idempotent and POST requests are generally not. This means that data in $_GETand $_POSTshould generally be used in different ways.

GET 请求应该是幂等的,而 POST 请求通常不是。这意味着,在数据$_GET$_POST一般应该以不同的方式使用。

If your application is using data from $_REQUEST, it will behave the same for both GET and POST requests, which violates the idempotence of GET.

如果您的应用程序使用来自 的数据$_REQUEST,则它对于 GET 和 POST 请求的行为将相同,这违反了 GET 的幂等性。

回答by Dereleased

$_REQUESTis generally considered harmful for the same reason that simple-to-medium-complexity data-transformations are often performed in the application code instead of declared in SQL: some programmers suck.

$_REQUEST通常被认为是有害的,原因与简单到中等复杂度的数据转换通常在应用程序代码中执行而不是在 SQL 中声明的原因相同:一些程序员很糟糕。

As such, if one tends to use $_REQUESTeverywhere, I can do anything via GET that I could via POST, which means setting up <img>tags on my (malicious) site that cause users logged into your e-commerce module to purchase products silently, or I can cause them to click on links that will result in dangerous actions or the revelation of sensitive information (probably to me).

因此,如果有人倾向于在$_REQUEST任何地方使用,我可以通过 GET 做任何我可以通过 POST 做的事情,这意味着<img>在我的(恶意)站点上设置标签,导致用户登录您的电子商务模块以静默方式购买产品,或者我可能会导致他们点击链接,从而导致危险的行为或敏感信息的泄露(可能对我而言)。

However, this is because of a novice, or at least inexperienced, PHP programmer making simple mistakes. First off, know when data of what type is appropriate. For example, I have a web service which can return responses in URLEncoding, XML or JSON. The application decides how to format the response by checking the HTTP_ACCEPT header, but can be coerced into one specifically by sending the formatparameter.

然而,这是因为新手,或者至少是没有经验的 PHP 程序员犯了一些简单的错误。首先,知道什么类型的数据是合适的。例如,我有一个 Web 服务,它可以以 URLEncoding、XML 或 JSON 格式返回响应。应用程序通过检查 HTTP_ACCEPT 标头来决定如何格式化响应,但可以通过发送format参数将其强制转换为特定格式。

When checking the content of the format parameter, it could be sent via querystring or a postdata, depending on a multitude of factors, not the least of which being whether or not the calling applications wants "&format=json" mixed in with its request. In this case, $_REQUESTis very convenient because it saves me having to type something like this:

在检查格式参数的内容时,它可以通过查询字符串或 postdata 发送,这取决于多种因素,其中最重要的是调用应用程序是否希望将“&format=json”混入其请求中。在这种情况下,$_REQUEST非常方便,因为它使我不必键入以下内容:

$format = isset($_POST['format']) ? $_POST['format'] 
    : (isset($_GET['format']) ? $_GET['format'] : null);

I'm not going to ramble on much further, but suffice to say that $_REQUESTusage is not dissuaded because it is inherently dangerous - it's just another tool that does exactly what is asked of it, whether you understand those implications or not - it is the poor, lazy or uninformed decision of a poor, lazy or inexperienced programmer that causes this problem.

我不会再多说,但可以说$_REQUEST并没有劝阻使用,因为它本质上是危险的——它只是另一种工具,它完全按照要求执行,无论你是否理解这些含义——它是导致此问题的贫穷、懒惰或缺乏经验的程序员的糟糕、懒惰或不知情的决定。

How to use $_REQUESTsafely

如何$_REQUEST安全使用



  1. Know your data: You should have some expectation as to what kind of data you will get, so sanitize it accordingly. Data for a database? addslashes()or *_escape_string(). Going to show it back to the user? htmlentities()or htmlspecialchars(). Expecting numerical data? is_numeric()or ctype_digit(). In fact, filter_input()and its related functions are designed to do nothing but check and sanitize data. Use these tools, always.
  2. Don't access user-supplied superglobals data directly. Make a habit of sanitizing your data, every time, and move your data to clean variables, even if it's just $post_clean. Alternatively, you can just clean directly in the superglobals, but the reason I advocate using a separate variable is because doing so makes it easy to spot vulnerabilities in code, as anythingpointing directly to a superglobal and not its sanitized equivalent is considered a dangerous error.
  3. Know where you data should be coming from.Referencing my example from above, it is perfectly reasonable to allow the response format variable to be sent via GET or POST. I also allow the "action" variable to be sent via either method. However, the actions themselves have very specific requirements as to which HTTP Verb is acceptable. Functions, for example, that make changes to data used by the service may only be sent via POST. Requests for certain types of non- or low-privilege data (such as dynamically generated map images) may be served in response to requests from either method.
  1. 了解您的数据:您应该对将获得什么样的数据有一些期望,因此请相应地对其进行清理。数据库的数据? addslashes()*_escape_string()。要把它展示给用户吗?htmlentities()htmlspecialchars()。期待数字数据? is_numeric()ctype_digit()。事实上,filter_input()它的相关功能旨在检查和清理数据。始终使用这些工具。
  2. 不要直接访问用户提供的超全局数据。养成每次清理数据的习惯,并将数据移动到干净的变量中,即使它只是$post_clean. 或者,您可以直接在超全局变量中进行清理,但我提倡使用单独的变量的原因是因为这样做可以很容易地发现代码中的漏洞,因为任何直接指向超全局变量而不是其经过消毒的等效项都被认为是危险的错误.
  3. 知道您的数据应该来自哪里。参考我上面的示例,允许通过 GET 或 POST 发送响应格式变量是完全合理的。我还允许通过任一方法发送“action”变量。但是,动作本身对可接受的 HTTP 动词有非常具体的要求。例如,对服务使用的数据进行更改的函数只能通过 POST 发送。可以响应来自任一方法的请求来提供对某些类型的非或低权限数据(例如动态生成的地图图像)的请求。

In conclusion, remember this simple rule:

总之,记住这个简单的规则:

SECURITY IS WHAT YOU MAKE IT, PEOPLE!

安全就是你做的,伙计们!

EDIT:

编辑:

I stronglyrecommend bobince's advice: if you can, set the request_orderparameter in php.ini to "GP"; that is, no cookie component. There is almost no rational reasoning for this in 98%+ of cases, as cookie data should almost never be considered comparable to the querystring or to postdata.

强烈推荐 bobince 的建议:如果可以,将request_orderphp.ini 中的参数设置为“GP”;也就是说,没有 cookie 组件。在 98% 以上的情况下,几乎没有合理的推理,因为 cookie 数据几乎不应该被视为与查询字符串或 postdata 相比较。

P.S., Anecdote!

PS,轶事!

I knew a programmer who thought of $_REQUESTa place to simply store data that was accessible in a superglobal way. Important usernames and passwords, paths to files, you name it and it was stored in $_REQUEST. He was a bit surprised (although not comically so, unfortunately) when I told him how that variable behaves. Needless to say, that practice has been deposed.

我认识一位程序员,他想出了$_REQUEST一个地方来简单地存储可以以超全局方式访问的数据。重要的用户名和密码、文件路径、您命名并存储在$_REQUEST. 当我告诉他这个变量的行为时,他有点惊讶(虽然不是很可笑,不幸的是)。不用说,这种做法已被废除。

回答by Sampson

It's vague. You don't reallyknow how the data got to you since it carries post, get, and cookie data. I don't necessarily think that is always a bad thing, unless you needto know or restrict the method of delivery.

这很模糊。您并不真正知道数据是如何到达您的,因为它带有 post、get 和 cookie 数据。我不一定认为这总是一件坏事,除非您需要了解或限制交付方式。

回答by Eric Petroelje

I actually like using it. It gives you the flexibility to use GET or POST which can come in handy for things like search forms where most of the time data is POSTed, but sometimes you'll want to say link to a particular search, so you can use GET parameters instead.

我实际上喜欢使用它。它为您提供了使用 GET 或 POST 的灵活性,这对于大多数时间发布数据的搜索表单之类的事情会派上用场,但有时您想说特定搜索的链接,因此您可以改用 GET 参数.

Also, if you look at many other languages (ASP.NET for example) they make no distinction between GET and POST variables at all.

此外,如果您查看许多其他语言(例如 ASP.NET),它们根本没有区分 GET 和 POST 变量。

ETA:

预计到达时间

I've never used REQUEST to get COOKIE values, but I think Kyle Butt makes a great point in the comments on this post about that. It is NOT a good idea to use REQUEST for getting COOKIE values. I believe he is right that there is some real potential for cross-site request forgery if you do that.

我从未使用 REQUEST 来获取 COOKIE 值,但我认为 Kyle Butt 在这篇文章的评论中提出了一个很好的观点。使用 REQUEST 获取 COOKIE 值不是一个好主意。我相信他是对的,如果你这样做,跨站点请求伪造有一些真正的潜力。

Also, the order in which stuff gets loaded into REQUEST is controlled by configuration parameters in php.ini (variables_order and request_order). So, if you have the same variable passed in via both POST and GET, which one actually gets into REQUEST depends on those ini settings. This could affect portability if you depend on a particular order and those settings are configured differently than you expect them to be.

此外,将东西加载到 REQUEST 的顺序由 php.ini 中的配置参数(variables_order 和 request_order)控制。因此,如果您通过 POST 和 GET 传递了相同的变量,那么实际进入 REQUEST 的变量取决于这些 ini 设置。如果您依赖特定的顺序并且这些设置的配置与您预期的不同,这可能会影响可移植性。

回答by Kyle Butt

It's important to understand when to use POST, when to use GET and when to use a cookie. With $_REQUEST, the value you're looking at could have come from any of them. If you expect to get the value from a POST or a GET or from a COOKIE, it's more informative to someone reading your code to use the specific variable instead of $_REQUEST.

了解何时使用 POST、何时使用 GET 以及何时使用 cookie 很重要。使用 $_REQUEST,您正在查看的值可能来自其中任何一个。如果您希望从 POST 或 GET 或从 COOKIE 获取值,那么阅读您的代码的人使用特定变量而不是 $_REQUEST 会提供更多信息。

Someone else pointed out also that you don't want to all POST's or cookies to be overridden by GETs because there are different cross-site rules for all of them, for instance, if you return ajax data while using $_REQUEST, you are vulnerable to a cross site script attack.

其他人还指出,您不希望所有 POST 或 cookie 都被 GET 覆盖,因为所有这些都有不同的跨站点规则,例如,如果您在使用 $_REQUEST 时返回 ajax 数据,您很容易受到攻击跨站脚本攻击。

回答by Jani Hartikainen

The only time using $_REQUESTis not a bad idea is with GET.

唯一一次使用$_REQUEST不是一个坏主意是使用 GET。

  • If you use it to load POST values, you risk cross-site request forgeries
  • If you use it to load cookie values, you again risk cross-site request forgeries
  • 如果您使用它来加载 POST 值,则存在跨站点请求伪造的风险
  • 如果您使用它来加载 cookie 值,您将再次面临跨站点请求伪造的风险

And even with GET, $_GETis shorter to type than $_REQUEST;)

即使使用 GET,$_GET输入也比$_REQUEST;)

回答by Brian T Hannan

I might be used only if you want to retrieve the current url or hostname, but for actually parsing data from that URL such as parmeters using the & symbol it's probably not a good idea. In general, you don't want to use a vague description of what you are trying to do. If you need to be specific that's where $_REQUEST is bad, if you don't need to be specific then feel free to use it. I would think.

我可能只在您想检索当前 url 或主机名时使用,但对于实际解析来自该 URL 的数据,例如使用 & 符号的参数,这可能不是一个好主意。通常,您不希望对您要执行的操作使用含糊的描述。如果您需要具体说明 $_REQUEST 不好的地方,如果您不需要具体说明,请随意使用它。我会想。