PHP offers a convenience superglobal called $_REQUEST that coalesces input from a number of sources into one easy to use array. A common thought amongst PHP developers is that you should avoid the use of $_REQUEST -- but do you actually know why?

The prevailing misconception seems to be that having GET and POST variables mixed together is insecure. While this is true under some specific circumstances (see Cross-Site Request Forgeries for a weak example) -- it isn't the main reason why $_REQUEST is insecure. In fact, combining GET and POST data is often a very useful feature. In many cases you don't really care if a variable comes from GET or POST and so using $_REQUEST in those situations can help reduce the verbosity of your code while increasing flexibility.

The real problem is that COOKIE data is also mixed into $_REQUEST. The implications of this may not be readily apparent until you start thinking like a malicious user. Any cookie ever set on a users machine will always override any GET or POST data -- creating "sticky" variable data.

For instance, imagine if your application uses "action=" or "do=" switches to control page commands. If an attacker some how managed to set a cookie -- perhaps through some Javascript injection -- he could set a cookie named "action" and give it the value "logout." Any users that fell victim to the cookie set would never be able to use your application because "action" would be permanently set to "logout."

So to sum it up:

Question: Why is $_REQUEST insecure?
Answer: Because it combines COOKIE as well as GET and POST, and the COOKIE data always takes precedence -- creating the possibility for dangerous "sticky" variables.

Solutions

If you're already using PHP 5.3, then you can edit your php.ini and check the request_order variable -- make sure 'C' removed. This 'C' is removed by default, but if you use a shared host it might've been put back for backwards-compatibility. Make sure to check!

Otherwise, you can easily just create your own $_REQUEST array by merging $_GET and $_POST manually as part of your global initialization routines.

  1. $_REQUEST = array_merge($_GET, $_POST);

And finally, best practice is to abstract your input reading out (see Stop using superglobals!) so you can define yourself exactly how variables are read and from where.

15 Responses to “Why PHP’s $_REQUEST is dangerous”

  1. Spyros Says:

    Well, no..

    There is absolutely no security problem with using $_REQUEST. Getting input from cookie is the same as getting input from get or post.

    If $_REQUEST was indeed a security flaw in PHP, it would have been removed.

  2. Christopher Nadeau Says:

    Did you not read the article at all?

    The fact that cookie data takes *precedence* in $_REQUEST over the others is the dangerous part. Indeed, even if it was last, it would still be dangerous for the simple fact that a specific value would could always be set.

    No one wants to remove $_REQUEST itself from PHP. Only cookie data should be removed. In PHP 5.3 we have the 'request_order' php.ini setting which has cookies disabled by default:

    request_order
    Note that the default distribution php.ini files does not contain the 'C' for cookies, due to security concerns.

  3. Toby Says:

    Cheers for the explanation, my php.ini was clean but it is a good thing to be looking out for.

    I have seen a lot of code floating about that would check against $_REQUEST using if(isset($_REQUEST['wibble'])), just calling the script with script.php?wibble=y will trigger this even if it is a $_POST variable that should be being checked.

  4. Useful Security Pages | Toby's Development Blog Says:

    [...] Why $_REQUEST is dangerous [...]

  5. php mail() validation Says:

    [...] $_COOKIE as usual. I found a nice text explaining why $_REQUEST has a problem, so read for example Why PHP’s $_REQUEST is dangerous - Devlog and see what the problem really is, and how you can avoid the problem. [...]

  6. Jeremy Simkins Says:

    I make it a point to never use $_REQUEST. Even studying for the ZCE explains that $_REQUEST is a major security risk. Spyros, you are completely wrong.

    Thanks for the article, very useful information. Let's hope people learn from this...

  7. Christian Sciberras Says:

    Jeremy did you even read the article? Spyros is wrong, but so are you.

    The author specifically said that $_REQUEST is only insecure because of $_COOKIE in request_order, which for your information, has been disabled for quite some time.

    So to sum it up, $_REQUEST, is a very useful feature which is best used with newer versions of PHP.

    There are no other ulterior "major security risks".

  8. Roberto Neumann Says:

    Correct me if I´m wrong, but this sounds like $_COOKIE was the only $_REQUEST-element that can be misused by users. But considering GPC, all three arrays do usually get user-input - so whereever you´re using $_REQUEST, even if the C has been removed, the user could still give you some faulty data to deal with, because the user can still infuse them via $_GET (address bar) or $_POST (using a local HTML form to call your php-file).

    So there is no true point in removing C from GPC, because all three arrays are ultimately user-controlled and have to be dealt with! Changing its priority makes much more sense in my opinion -> CGP. You´ll just fix some possible bugs either way, but there´s always a risk to deal with when dealing with user-controlled variables - no matter where they come from.

  9. Miguel Cruz Says:

    Roberto: You are missing the point.

    It's true that all user data is fundamentally untrustable.

    However, the thinking in your message is all about protecting the server from compromise. That's not the issue here. The issue here is protecting users from abuse.

    Allowing cookie data to mingle with form data doesn't change the vigilance that is necessary in order to prevent your server from compromise.

    However, it does make it easier for miscreants to trick unwitting users into unwittingly performing actions on your server which they are nominally allowed to do but might not have chosen to.

  10. Onto Development Says:

    The example in this article of Cookie abuse misses a more important development point.

    "If an attacker some how managed to set a cookie -- perhaps through some Javascript injection ..."

    Sounds like you have bigger issues on your hands if this happens. Lock down your user content and you won't have this problem or the other hundreds of malicious injections, many much worse than a simple prevention of use of your site.

  11. 為何在 PHP 中盡量不要使用 $_REQUEST « Ant's ATField Says:

    [...] Why PHP’s $_REQUEST is dangerous [...]

  12. 為何在 PHP 中盡量不要使用 $_REQUEST » Blogs of OpenFoundry - OpenFoundry團隊非官方網誌串聯平台 Says:

    [...] Why PHP’s $_REQUEST is dangerous [...]

  13. Web Farmer Says:

    hi folks,

    I'm not agree with "Any cookie ever set on a users machine will always override any GET or POST data -- creating "sticky" variable data"

    Because in php.ini
    variables_order = "GPCS"(wrt php 5.2.8)

    So GET/POST form value never ever be overwritten by Cookie.

    Thanks,
    Sachin Pethani

  14. Wil Moore III Says:

    The arguments that "GET/POST" will _never_ be overwritten are shortsighted at best. The simple fact that this is something that can be set in php.ini (most ridiculous _feature_ of a programming language BTW) means you should still steer clear. If you never ship software or never have to support software in the wild, this is easy to dismiss; however, it is a problem. Would you really want to potentially introduce subtle bugs and security gaps?

  15. James Says:

    I don't understand why everyone is down-talking this article. It's still educational. And yes, if the $_COOKIE value was removed from $_REQUEST, that would be awesome, and I would change a lot of my code so I didn't have to look for both $_GET and $_POST. But for now, it will remain the same.

Leave a Reply