Does PHP's $_REQUEST method have a security problem? - php

The textbook I read says that $_REQUEST has security problem so we better use $_POST.
Is this OK?

I would say that it is dangerous to characterise $_POST as more secure than $_REQUEST.
If the data is not being validated and sanitized before being used, you have a possible vector of attack.
In short:
It doesn't matter where the data comes from if it is not being handled in a secure manner.

Well, the reason that $_REQUEST has issues is that it picks up values from $_GET, $_POST, and $_COOKIE, which means that if you code things certain ways and make certain invalid trusting-the-client assumptions, a malicious user could take advantage of that by supplying a value in a different place than you expected and overriding the one you were trying to pass.
This also means that you may have given your henchman incorrect instructions, because it may have been a GET or COOKIE value that he was picking up from $_REQUEST. You would need to use whatever place the value you're looking for actually shows up, not necessarily $_POST.

As was mentioned already in several answers: Any data coming from the client cannot be trusted and must be treated as being malicious by default. This includes $_POST, $_GET, $_COOKIE and $_REQUEST (the combination of the former) but others as well.
When talking about some of them being more dangerous than others I would indeed separate $_GET and $_REQUEST (as it includes $_GET) out from $_POST, as it is slightly harder to generate, i.e. manipulate, a POST request than a GET request. The emphasis here is slightly, but using POST for sensitive operations at least removes another layer of low hanging fruits to exploit.
Especially when it comes to Cross Site Scripting (or XSS) and cookie theft, it is rather easy to get a victim's browser to issue a GET request to the server under attack by simply inserting a hidden image with a manipulated URL into a page or forging a link.
Issuing a POST request at least requires some JavaScript, which is slightly harder to inject into the victim's browser for execution (depending on the situation). Obviously POST requests can be generated by attackers directly, so they can't be trusted either, but for scenarios where an attacker is going through a 3rd party browser, they are a little bit harder to manipulate.
Security is always about making it as hard as possible to break your application - taking implementation constraints etc. into account. It can never be about being 100% secure. So it's best practise to choose the alternative which is more difficult to exploit, even if the difference is marginal, when having the choice between different implementation approaches.
In the end it is always about removing low hanging fruits. Sure, POST requests can be manipulated as well, but for any operation that has an elevated risk, use a POST request and restrict yourself to using $_POST in your code. That way you have have already excluded some very easy GET drive-by attacks and can now focus on validating your POST data. Just don't assume that using POST suddenly made the operation safe by default.

It's certainly okay to tell people to use $_POST instead of $_REQUEST. It is always better to be more sure about where your getting your data.

#Christian:
When talking about some of them being more dangerous than others I would indeed separate $_GET and $_REQUEST (as it includes $_GET) out from $_POST, as it is slightly harder to generate, i.e. manipulate, a POST request than a GET request. The emphasis here is slightly, but using POST for sensitive operations at least removes another layer of low hanging fruits to exploit.
Bzzt. Sorry, but this just ain't true.
Anybody who understands the difference between GET and POST or how unsanitized inputs might be exploitable, won't hesitate for a second to fire up Tamper Data.
Some people have it right here: there is NO security lost or gained by using $_REQUEST in a well-designed system.

There's no real security difference between using $_POST and $_REQUEST, you should sanitise the data with equal scrutiny.
The biggest problem with $_REQUEST is you may be trying to get data from a POST'd form, but might have a GET parameter with the same name. Where will the data come from? It's best to explicitly request the data from where you expect it, $_POST in that example
There are slight security benefits - it's easier to perform XSS (more specifically XSRF) attacks on GET parameters, which is possible if you use $_REQUEST, when you really just want POST data..
There's very few situations when you need data either from POST, GET or cookie.. If you want to get POST data, use $_POST, if you want to get data from from GET parameters, use $_GET, if you want cookie data, use $_COOKIE

The most secure way is to verify and validate the data. I usually generate a random unique id for a form and store it in the user's session, but this is easily bypassed by a determined attacker. Much better is to clean up all incoming data. Check out htmlspecialchars() and its related function. I also use a third party utility for cross-site, like HTML Purfier
On some practical notes, always use intval() what is supposed to be numeric, escape all incoming strings, use regex for phone numbers, emails or anything that is going to be part of a SQL query.
Hope this helps.

Related

Do I always need to validate request variables

Do I always need to validate user input, even if I'm not actually saving them to a db, file, or using them to include files etc..
Say I just wanted to echo out a request variable or I was using it to send email, is there any need to validate or sanitise it? I've always heard people say that all user input should be checked before doing anything with it, but does it actually pose any threat, if I'm not doing any of the above?
I wouldn't recommend it.
my rule is - NEVER TRUST USER'S INPUT.
lets say that your'e working on a team.
as you wrote, you build a simple form that submit the data to php file and than mail it.
after 3 weeks another team mate wants to use that form.
he's assuming that the data in the php file is clean . he dont know that you dont filtered it.
this is a crack for troubles.
Do I always need to validate user input, even if I'm not actually saving them to a db, file, or using them to include files etc..
Everything you are going to do with user supplied data depends on the context in which you are going to use it. In your single sentence you are already talking about 3 different contexts (db, file, include). Which all will need a different strategy to prevent things for that specific context.
Say I just wanted to echo out a request variable or I was using it to send email, is there any need to validate or sanitise it?
There are more things you can do besides validating and sanitizing. And yes you should handle this case (which is another context btw). Basically you should handle all user data as if it is malicious. Even if you are "just echoing it". There are numerous things I could do when you are "just echoing".
Considering we are in the context of a HTML page I could for example (but not limited to) do:
<script>location.href='http://example.com/my-malicious-page'</script>
Which can be for example an exact copy of you website with a login form.
<script>var cookies = document.cookie; // send cookieinfo to my domain</script>
Which can be used to get all your cookies for the current domain (possibly including your session cookie). (Note that this can and imho should be mitigated by setting the http only flag on the cookies).
<script>document.querySelector('body')[0].appendChild('my maliscious payload containing all kinds of nasty stuff');</script>
Which makes it possible to sideload a virus or something else nasty.
<!--
Fuck up your layout / website. There are several ways to do this.
I've always heard people say that all user input should be checked before doing anything with it
This is mostly wrong. You only need to decide how you are going to handle a piece of data once you know what you are going to do with it. This is because you want to prevent different things in different situations. Some examples are (but not limited to): directory traversal, code injection, sql injection, xss, csrf.
All above attack vectors need different strategies to prevent them.
but does it actually pose any threat, if I'm not doing any of the above
yes totally as explained above. All data that is coming from a 3rd pary (this means user input as well as external services as well as data coming out of the database) should be treated as an infectious disease.

Why is it bad to pass password values/important info using the $_GET['value'] PHP function?

Which is better to use with sensitive information $_REQUEST or $_POST? I'm trying to do this as securely as possible, could anyone see the value with either functions?
If you are not using SSL, then anyone will be able to read EITHER of those with ease. If you want to send information securely, you need to consider a secure transport such as SSL / https://
Passing it through $_GET basically means sending it as part of the URL.
However, neither $_REQUEST nor $_POST are as secure. Encrypt your data before sending, and be sure to salt your passwords.
It's recommended to use post because it prevents bookmarking the url with the password in it or leaving the browser session open.
As with all security it's just a layer - even using POST you could still examine the request with a HTTP Proxy such as fiddler or look in firebug. If you want real security you should use SSL also.
As well as the points others have mentioned, using GET will mean the password will show up in log files, which isn't very secure, e.g.
GET http://example.com/login/process?email=tom#jones.com&password=its_not_unusual
Your best bet is to POST with SSL.
It is generally bad to pass important information using the query string as it very easy for a user to modify the variables passed. Post variables are not so easy to tamper with.
I have seen a website where sql statements where passed through the url, and another where php commands were passed and then executed with exec(), this is stupid beyond belief.
$_REQUEST returns as well the $_POST, the $_GET as the $_COOKIE variables. Sending passwords this way is nood a good idea. Try checking the passwords in your php and adding the active user to your $_SESSION
That's not functions used to pass something but rather arrays, used to access passed data.
POST method should be used and $_POST array to access posted data,

Is it wrong to use $_REQUEST for Data?

So, I've been coding for a little (2 years), and I have a very subjective question:
Is it wrong to use $_REQUEST for Data?
This mainly pertains to authentication by the way.
If you think about the 3 ways data can occur in $_REQUEST, it can come from either a cookie, a form, or a query string. Now, I know that most people directly grab the information from either $_POST or $_GET, using $_COOKIE only when they are expecting a cookie.
My theory is that in reality, there shouldn't be any difference in this data, and it shouldn't make any difference if you replaced $_POST or $_GET with $_REQUEST.
If you are authenticating a user into the system, does it really mattered if the authentication details are contained in the $_POST or $_GET array? Heck, it probably shouldn't matter if they are in $_COOKIE either. They are still giving you credentials to log into the site, which you should check for correctness, and if so log them in.
Now, I do realize there are security issues if you try to have a login form that submits data via a query string, but I don't believe that pertains to the question. Also, if someone fails a login too many times, there should be proper limits set in place to avoid overloading the server.
I'd like to here the opinion about this.
Community Wiki'd for good measure.
Oh, and just by the way, here are other StackOverflow questions that relate if you have other questions about $_REQUEST
Why should I use $_GET and $_POST instead of $_REQUEST?
When and why should $_REQUEST be used instead of $_GET / $_POST / $_COOKIE?
In "good" coding practice, you want to disambiguate as much as possible.
Since $_REQUEST contains the data from $_POST, $_GET, and $_COOKIE by default, the value held by the variable that stores the data retrieved using $_REQUEST will be ambiguous as to which method it came from.
If we are more specific, it will benefit readability of code, as well as understanding of logic, and helps for debugging in the future.
(Let alone the security issues concerning each method, especially the $_GET one)
I'd say avoid it all together. I agree with Sev that disambiguation is important for many reasons (debugging, clarity/self-documentation, elegance, etc.), but there are significant security issues that could arise, and that would be my main reason for avoiding it.
As a simple example, what happens when the same key is sent in two of the arrays (e.g. $_POST['criticalInfo'] and $_GET['criticalInfo'])? As with most security issues, the vulnerabilities present themselves in the individual implementation, so it would be impossible to guess your specific risks. The fact is that ambiguity often opens up holes.
Don't leave it up to "variables_order" in PHP_INI to determine where your script gets variables from. Use $_GET, $_POST, etc.
It is also about not letting credentials come in any other way than a POST request. I would not want my GET request to have side-effects (like logging in the user).
Is it wrong? No.
Is it inferior to $_GET or $_POST? Yes. Use the right array and you'll avoid all kinds of problems that stem from not knowing where the array contents of $_REQUEST came from.

Passing base64_encoded serialized data between form submissions

I'm creating a wizard-based series of forms for taking user inputs. One of the requirements for that wizard is that the script (PHP) cannot save the inputs into the database (MySQL) until the user clicks the 'Save' button, so I have to device a mechanism to transport user inputs in one form to another when the user clicks 'Previous' or 'Next' buttons. I looked into using various methods including cookies, sessions, temporary files etc, but I settled for embedding base64_encoded serialize data in a hidden field that exists in all the forms in the series. The value in this field will be decoded on form submissions and re-encoded for putting in the next form after other values from the current form are inserted.
Here is a sample of how the hidden field looks:
<input type="hidden" name="wizard:presave" value="YTo2OntzOjU6InRpdGxlIjtzOjEwOiJRdWVzdGlvbiAyIjtzOjQ6InRleHQiO3M6MTk6IlllcyBpdCdzIGEgcXVlc3Rpb24iO3M6NDoidHlwZSI7czo2OiJjaG9pY2UiO3M6NzoiY2hvaWNlcyI7YTowOnt9czo1OiJwb2ludCI7aToxO3M6Mjoib3AiO3M6MTM6ImVkaXRfZXhlcmNpc2UiO30=" />
So the questions are:
Is it considered a good/bad practice?
Is there any length limit of hidden fields in HTMLform?
What are the possible security issues?
And are there better alternatives? (with explanations, preferably without using javascript)
Thanks in advance!
I've never seen this particular method of parameter passing in my career, so I can't say whether it's good or bad. It's certainly not "standard". Standard methods would either be passing the submitted method along (unencoded/normally) using hidden inputs, or storing in session. I think you might be making work for yourself, so in that sense it would lean towards "not ideal".
As long as you are using POST for your forms, there is no defined limit for data sizes that I'm aware of in the HTTP specifications. Older servers may have practical limits, but unless you're doing something extreme such as media file uploads, they shouldn't be a worry.
Possible security issues are the normal web security flaws. Anything you take from a user and re-output to a page could contain cross-site scripting vulnerabilities and would have to be properly sanitized (this is somewhat moot if you're encoding everything). Users can craft their own data and submit it if they like. Basically, assume all the data you handle is unsafe and tainted.
Sessions would work much better here. The data the user submits wouldn't have to go through a lengthy encoding process. As well, you'd only have to validate it once. After it's been submitted and validated, you can simply store it on the server in $_SESSION and leave it alone until the final button is clicked. Otherwise, you have to worry about re-outputting it, re-receiving it, and re-validating it at each step. A malicious user could submit one set of data, have it checked and re-output as encoded data, but then craft the next form submission by unencoding, changing data, and re-encoding.
I would highly recommend that you reconsider sessions, as it simplifies all your data operations into a "do-once" scenario.
Is it considered a good/bad practice?
Depends on the purpose. As far I've only seen such constructs as a client side URL hash to remember the state of the selections in large ajax-based applications (so that they are bookmarkable) and then often also Gzipped to make it shorter. In your speficic case I'd say: make use of the HTTP session and only pass a request based identifier (also called token) in the hidden field so that you can get the associated information from the session.
Is there any length limit of hidden fields in HTMLform?
In GET the complete query string (all parameter names and values and separators together) is usually limited to 2048 characters, but you can better adhere an officious limit of 256 chars. In POST it is dependent on server configuration. Often this defaults around 2GB.
What are the possible security issues?
Well, it is obviously decode-able.
And are there better alternatives? (with explanations, preferably without using javascript)
You could Gzip it to make it shorter and less obvious. Or, as already said, make use of the session in combination with a request based identifier.
Well, you can store into the session either by serializing or just simply store it the way it is for each step. When the user clicks Save, you grab and validate the data from all the steps in the session.
tsk tsk :)
Is it considered a good/bad practice?
subjectively - bad practice..you're using the wrong hammer for the job.
Is there any length limit of hidden fields in HTMLform? - Not sure if there is a limit.
What are the possible security issues? - Possibly, quite a few, but you can sanitize the data received for every request. Besides, the data is pretty easy to decode and can be easily modified on the client side (I can see that its some sort of json that you are using :) )
And are there better alternatives? (with explanations, preferably without using javascript) - Use the right tool .. sessions perhaps?
And yes... You are most likely going to face performance and scalability issues (should you have a substantial user load) with all that sanitizing, parsing, formatting and security code running for every request.

When posting info from a form, is it better to use $_REQUEST or $_POST?

I have a form a user can enter their name, then it will add it to $message to be sent in an email.
Is it better to use $_POST or $_REQUEST?
Here is a snippet of using $_REQUEST
$message.= "Name: ".$_REQUEST["fname"]." ".$_REQUEST["mname"]." ".$_REQUEST["lname"]."\n";
My approach used to be to use $_REQUEST for everything which I think is a big mistake. Lately, I've been trying to be more diligent about using GET only for read-requests & POST only for write-requests.
To that end, I think using $_GET for GET requests & $_POST for POST requests makes my intent much more clear in my code.
The answer is: It depends on how you want it to be used.
If you're using $_POST, that means it can only come in via POST.
If you're using $_REQUEST, that means you accept POST, GET (and COOKIE, but it's mainly the first two we're interested in).
For something like this, $_POST would probably be neater, but if you were making a search engine, allowing to set up a search URL would probably be a good idea. However, you might want to allow for a ton of special parameters to narrow down the search, and if that can take up a lot of URL space, you'll probably want to allow POSTDATA as well.
As Dylan mentions, keep in mind that neither is a replacement for any kind of security.
doesn't matter which one you use. just make sure you use some form of security with forms.
I just listened to Security Now episode #166 which was all about cross-site request forgery, and in it, Steve makes a good case for using $_POST for forms rather than $_REQUEST. (Indirectly, he doesn't talk about PHP itself, but does say that you shouldn't accept both GET and POST for forms.) The reason is that it's easy to use GET requests for CSRF attacks but not so easy to use POST.
Using $_POST itself doesn't eliminate the possibility of CSRF attacks, but it does reduce it. Steve also suggests using a cryptographically strong pseudo-random hidden field in the request that will eliminate the possibility of "blind" requests.
_POST if data is being updated somewhere (i.e. if the action has a side-effect), _REQUEST otherwise, and if you don't care whether or not the data comes via GET, POST, or any other method.
Unless you have a good reason to do otherwise (such as the search engine mentioned by Michael), it's probably better to use $_GET and $_POST for their respective methods instead of $_REQUEST, to avoid any ambiguity or confusion over possibly having the same argument name in the GET and POST data.
The only time I use $_REQUEST is when I need to be able to support data from either $_POST or $_GET.
For example, if I have a form that's supposed to modify a record, I might initially pass the record ID in the url as id=X. So when first loading the form, I could use $_GET['id'] to figure out what record we're trying to modify.
However, when submitting the modify operation, the form should be POSTed, since it will be changing data and is not idempotent. In this case, the record ID would be accessible as $_POST['id'] when processing the form submission.
But what happens if there's an error in the form submission and I need to reload the form with a helpful error message? In this case, the form generation code needs to figure out what record to use by looking at the POSTed id, which is not in the URL.
In cases like this, I would use $_REQUEST['id'] in the form display logic, so that it could support either scenario. But for form processing, I would use $_POST['id'] for strict checking.

Categories