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.
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.
April 27th, 2010 at 12:29 pm
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.
April 30th, 2010 at 4:44 pm
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:
May 5th, 2010 at 2:42 am
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.
May 5th, 2010 at 3:43 am
[...] Why $_REQUEST is dangerous [...]
May 12th, 2010 at 3:22 am
[...] $_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. [...]
May 26th, 2010 at 11:19 am
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...
July 16th, 2010 at 5:54 pm
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".
September 10th, 2010 at 11:08 pm
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.
September 27th, 2010 at 6:53 am
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.
October 8th, 2010 at 11:16 am
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.
November 6th, 2010 at 1:20 pm
[...] Why PHP’s $_REQUEST is dangerous [...]
November 6th, 2010 at 9:32 pm
[...] Why PHP’s $_REQUEST is dangerous [...]
December 2nd, 2010 at 2:53 am
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
October 4th, 2011 at 11:54 am
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?
October 12th, 2011 at 10:58 am
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.