I want clear $_POST array content fully, all examples what I see in internet, looks like this:
if (count($_POST) > 0) {
foreach ($_POST as $k=>$v) {
unset($_POST[$k]);
}
}
Tell please, this variant will be not more better? (Point of view as saving resources)
if (count($_POST) > 0) {
$_POST = array();
}
or not ?
Yes, that is fine. $_POST is just another variable, except it has (super)global scope.
$_POST = array();
...will be quite enough. The loop is useless. It's probably best to keep it as an array rather than unset it, in case other files are attempting to read it and assuming it is an array.
To unset the $_POST variable, redeclare it as an empty array:
$_POST = array();
The solutions so far don't work because the POST data is stored in the headers. A redirect solves this issue according this this post.
How to delete $_POST variable upon pressing 'Refresh' button on browser with PHP?
It may appear to be overly awkward, but you're probably better off unsetting one element at a time rather than the entire $_POST array. Here's why: If you're using object-oriented programming, you may have one class use $_POST['alpha'] and another class use $_POST['beta'], and if you unset the array after first use, it will void its use in other classes. To be safe and not shoot yourself in the foot, just drop in a little method that will unset the elements that you've just used: For example:
private function doUnset()
{
unset($_POST['alpha']);
unset($_POST['gamma']);
unset($_POST['delta']);
unset($_GET['eta']);
unset($_GET['zeta']);
}
Just call the method and unset just those superglobal elements that have been passed to a variable or argument. Then, the other classes that may need a superglobal element can still use them.
However, you are wise to unset the superglobals as soon as they have
been passed to an encapsulated object.
You can use a combination of both unset() and initialization:
unset($_POST);
$_POST = array();
Or in a single statement:
unset($_POST) ? $_POST = array() : $_POST = array();
But what is the reason you want to do this?
To answer "why" someone might use it, I was tempted to use it since I had the $_POST values stored after the page refresh or while going from one page to another. My sense tells me this is not a good practice, but it works nevertheless.
Related
I'm reading a book on php security, and on input validation chapter there's a small section that talks about only allowing expected input.
This is the code that they show:
<?php
$expected = array( 'carModel', 'year', 'bodyStyle' );
foreach( $expected AS $key ) {
if ( !empty( $_POST[ $key ] ) ) {
${$key} = $_POST[ $key ];
}
else {
${$key} = NULL;
}
}
?>
I'm kind of confused, there's a small paragraph that explains what the code does. For what I get it assigns a value from the array as a key to $_POST. It also says that the array should be done programatically copied out of the GPC array.
What I don't understand is in what cases should I use this? And what is the GPC array?
GPC = Get Post Cookie, it's referring to variables coming from the user/browser. So instead of using $_GET, $_POST, $_COOKIE you should be cleaning and validating that data into a variable(s) that you can trust and know is clean.
As for the suggestion, what they are doing is limiting what your code has access to. In the above code example, you would probably have a form on the page with elements named carMOdel, year, and bodyStyle. What the code here is doing is restricting your code to ONLY interact with those 3 elements.
This prevents someone from passing extra parameters to your page in an attempt to inject code or some sort of SQL injection attack or any other number of things. In a simple example like this it might not make sense. But there are cases where people are taking form/api requests and running loops over everything in one of GPC arrays and doing stuff with anything in there. I would suggest not doing that to begin with.
This is just 1 of MANY things to protect your server/database. When developing webapps you should take the stance of trusting NOTHING that comes from the user side.
As far as security goes, OWASP is a great source for learning. here is a little cheat sheet that is in the works for php.
The code creates variables from data in the $_POST array. The names of the variables are taken from the keys of the $_POST array. PHP calls this (i.e. naming variables dynamically) variable variables.
This is usually a bad idea, because you do not control, which keys are present in the $_POST array, and thus, which variables are created. The user of your website controls this. A malicious user might name the POST variables in such a way that they overwrite variables that you intended for different purposes.
The book suggests to allow keys in the $_POST array to overwrite variables in a controlled manner. That's what $expected = array('carModel', 'year', 'bodyStyle') is for. This and the following code only creates the variables $carModel, $year and $bodyStyle. If, for example, a user posts current_user_has_admin_rights=1 to you application, a variable $current_user_has_admin_rights with a value of 1 will not be created.
My suggestion is to to stay away from variable variables alltogether and instead access the POST values through the $_POST array only. This makes it clear where the value comes from, an thus makes it easier to spot if such a value is handled in an unsecure manner.
It also says that the array should be done programatically copied out of the GPC array.
This could mean that you shouldn't necessarily write:
$expected = array('carModel', 'year', 'bodyStyle');
Rather write something like:
$expected = getExpectedInput('carForm');
Where the function getExpectInput would query the database for the input that should be in the form 'carForm'. Or perhaps it could be in a file and this function would fetch that content. They basically mean, it's not a good idea to hard-code the variables in the form. Rather write them somewhere so they are easy to change. If you ever made changes to the form and added a variable or changed a variable name, you don't have to change this particular code. This means that this function is usable on different forms. The idea is to write function that that can be re-used. Not those that are dedicated to one thing. OOP.
The getExpectedInput function would probably return an array. You can name this whatever you like or use any method.
I am thinking of making a loop to gather all my $_POST variables and assign them to dynamically named variables.Something like this (not tested)
for($i; $i <= $_POST[].length; $i++){
${$_POST[i]} = $_POST[i]
}
But I am wondering about the security of something like this. This would then create a variable in the system for every bit of post data sent to the page. Can that variable be damaging even if the script I write doesn't reference it? Is this the type of thing I should avoid entirely? I have some pages that send quite a few variables and a script like this would prevent a whole lot of writing, but is it safe enough?
Yes there are possible security risks.
Say you have a variable $is_admin defined earlier in the code that gives someone admin abilities. If someone POSTS to that page with
$_POST['is_admin'] = true;
Then $is_admin is now true. Not good.
What's wrong with using $_POST?
Yes there can be security concerns/problems, for example one could overwrite any local variables which are already set, like database, config values ect.
So something like this should be avoided:
$yourImportantVar = 'Something relies on this';
//User POSTS yourImportantVar=overwritten
foreach ($_POST as $key => $value) {
$$key = $value;
}
echo $yourImportantVar; //overwritten
But if you want to implement a loop to save a chunk of code, you could create an allowed array which you loop over and extract out the value from the $_POST.
foreach (array(
'name',
'address',
'somethingelse',
'ect'
) as $key) {
$$key = isset($_POST[$key]) ? $_POST[$key] : null;
}
This is a very bad idea for security and maintainability. Simplified example why...
<?php
if (someRandomSessionCheck()) {
$isAdminUser = true;
}
if ($isAdminUser) {
// give access to everything
}
?>
Someone could post to the page with a variable "isAdminUser=1" and would have access to everything.
Another reason it is a bad idea is you can't clearly see from the script where your variables are created. This reduces maintainability of the script. What if you now want to run the script but instead need to get the data from somewhere else and not a POST?
Only issue I can think of at the moment is when that overwrites the existing variable in the scope. This can be very unsafe depending on what you do with it. Think about the variable being the URL you are doing a HTTP request to. Or worse, some flag variable which accesses some critical part of your code.
I will post an example that speaks about HTTP request:
<?php
$url = "http://safe/url/to/POSTto";
$var = array("url" => "http://www.mysite.com/url"); //assume this is $_POST
foreach($var as $key => $value){
${$key} = $value;
}
//now upon the HttpRequest, your site can receive the (critical) data which was actually meant for the safe site.
?>
EDIT: #Galen has posted about the flag variable I was talking about, so may be I need not post any example to highlight the problem.
PHP had a feature (using the term loosely) called register_globals. It has since been deprecated (PHP 5.3) and removed (PHP 5.4), but it mirrored the functionality for which you are looking. It performed the same thing as the PHP function extract() does, which sets variables in the current scope with names of the keys and values of the matching array values.
This is most definitely a security risk. Consider the example of a poor check for authentication:
if($is_logged_in) {
// Allow execution of destructive actions
}
If this feature was enabled (or you mimicked it), a malicious user would be able to set the variable $is_logged_in and bypass the login screen. Don't worry about saving typing. If you need to copy and paste a code block like this at the beginning of your files:
$something = $_POST['something'];
$another = $_POST['another'];
$stuff = $_POST['stuff'];
//etc.
Not only is it much more secure, but it doesn't leave developers (who aren't expecting register_globals) puzzled when undeclared variables start being used. Also, the fact that PHP has removed it and there are plenty of arguments against its use should be evidence enough.
<?php
/* Suppose that $var_array is an array returned from
wddx_deserialize */
$size = "large";
$var_array = array("color" => "blue",
"size" => "medium",
"shape" => "sphere");
extract($var_array, EXTR_PREFIX_SAME, "wddx");
echo "$color, $size, $shape, $wddx_size\n";
?>
Please check this. Same thing what you are going do by using loop. may help you
You are basically implementing extract($_POST, EXTR_OVERWRITE) which will overwrite any already existing variables. The manual already warns to use extract in a way you do:
Do not use extract() on untrusted data, like user input (i.e. $_GET, $_FILES, etc.). If you do, for example if you want to run old code that relies on register_globals temporarily, make sure you use one of the non-overwriting extract_type values such as EXTR_SKIP and be aware that you should extract in the same order that's defined in variables_order within the php.ini.
This can result in overwriting essential and sensitive variables, including those that cannot really be modified directly like $_SESSION, $_SERVER, and $GLOBALS:
POST /foo.php HTTP/1.1
Content-Type: application/x-www-urlencoded
_SESSION[user]=admin
This would have the same effect as $_SESSION = array('user'=>'admin').
For example, I am using a $_POST variable to insert data into a DB. Just before this query I have a few tests and if they are true I want to adjust that (hidden) $_POST value.
Ex.
if($baby_dragon_eats_children){
$_POST['hidden_value'] = "grapes";
}
Can $_POST['hidden_value'] be assigned a new value and then be passed to another function as $_POST and be able to access the new $_POST['hidden_value']?
Thanks
$_POST['consolidate_answers']
IF you assign a value to $_POST you should document is very clearly as it is not common nor considered "best" practice.
IF you have any extensions of PHP such as Suhosin Patch... it may block such actions..
Handle your own arrays, don't depend on $_POST!
IF need be, make a copy of $_POST and work with that.
You can assign values to $_POST, but if you do so you should document it very clearly with comments both at the point of assignment and the later point of access. Manually manipulating $_POST can break future programmers' (including your own) expectations of what is in the superglobal and where it came from.
There may be other alternatives, like:
$my_post = $_POST;
$my_post['hidden_value'] = 12345;
// In a function:
function func() {
// Emulate a superglobal
echo $GLOBALS['mypost']['hidden_value'];
}
Can $_POST['hidden_value'] be assigned a new value and then be passed to another function as $_POST and be able to access the new $_POST['hidden_value']?
It can in normal PHP.
However, extensions like the Suhosin Patch may block this.
Also, it feels wrong in general. $_POST is intended to contain the raw, incoming POST data - nothing else. It should not be modified IMO.
A better way to go would be to fetch all the data you plan to insert into the database into an array, and do the manipulations in that array instead.
You can, it will work, but don't.
Create a copy of $_POST, perform your tests on that and modify that instead. For example.
$postdata = $_POST;
if ($postdata['somevalue'] != 'someothervalue') $postdata['newvalue'] = 'anothervalue';
// ...
If you manipulate variables auto-created by PHP, it will probably come back to haunt you later on when the variable doesn't hold the data you expect it to.
Find an alternative!
The $_POST variable has a distinct responsibility. Do not abuse its globalism.
I'd say don't abuse globalism either way, even if it means changing the design you have (or have in mind).
But if you choose not to, then consider creating a dedicated global registry just for your needs.
Don't manipulate language built-ins.
I'm trying to automate form creation and submission in codeigniter.
Basically what I want is to find a way to go over all the data in the POST array and format it correctly to an insert or update sql query.
The problem is I don't know how to access to whole POST array in CI, all I know of is the $this->input->post(field_name) way which only gives you a specific field.
Ideally I would want to send the POST array to the $this->db->insert_string() or $this->db->update_string() to do the job for me.
I know I can still use the php native $_POST array, but this is not recommended and not as secure as CI's input class.
Anyone know a way to do this?
Thanks,
Amos
Eventually I found out that the input class cleans the $_POST array automatically (not talking about XSS cleaning) and so the only advantage to use $this->input->post(something) is that it checks if that key exists.
Since I need the whole array I don't need that check and can safely use $this->db->insert_string($_POST).
If I you do want XSS cleaning you can either turn it on globally in the config or use geocine's answer (I would go for a mix of the 2 examples he gave).
Another way to go if you want the whole array with XSS cleaning and without it turned on globally is to go with WanWizard's Input library extension found here: http://codeigniter.com/forums/viewthread/172705/#821150
foreach($_POST as $key => $value) {
$value = $this->input->post($key);
//do something
}
or
$keys = array_keys($_POST);
for($i=0,$max=count($keys);$i<=$max;$i++)
{
$value = $this->input->xss_clean($_POST[$keys[$i]]);
//do something
}
if (isset ($_POST['somethingA']))
{
//code for doing something A
}
elseif (isset ($_POST['somethingB']))
{
//code for doing something B
}
I will need to access some data from somethingA code, into somethingB code.
How can I do that in a proper way?
Should I declare a variable outside the conditionals, work inside the conditionals, and later (bottom) I use that?
Should I work with them inside the conditionals, and, somehow, pull them out after the conditional lines?
Thanks in advance,
MEM
you may do something like you said:
$innervar = null;
if (isset ($_POST['somethingA']))
{
$innervar = new A();
//code for doing something A
}
elseif (isset ($_POST['somethingB']))
{
$innervar = new B();
//code for doing something B
}
$innervar->CommonMethod();
If you are accesing $_POST directly consider using some sort of framework like symfony, or Zend, unless you are learning or working in a very simple(house) project.
Best of luck
David
You should just declare the variable outside. So you can use and access the resources in both
According to your clarification the comments, you want to share data between two successive executions of the PHP script. That's not a question of where to put your variables in the ocde. You want the code to run once, compute some value, and then have this value available when the code is run again.
There are two ways of doing this:
Put the value into a hidden input field on the webpage
Put the value into the user session (which means it's stored "somewhere" by the PHP runtime and made available for all subsequent requests with the same session ID)