Php: can a user generate array in a post/get request? - php

I was dealing with security, and I came up with an idea:
if (!isset($_POST['id']))
{
$_POST['id'] = 0;
}
$_POST['id'] = (int)$_POST['id']; // kill SQL injection
but what if id was an array? It would force this method to knee! But I dont know if its even possible to generate array.

Don't reinvent the wheel: php has a nice set of filters to deal with $_GET and $_POST: see http://php.net/filter - there are filters even for arrays.
If in your form you have a <SELECT multiple>, which will send out an array of options picked by the user, the name must be something like name="MySelection[]" instead of a plain name="MySelection". In this way, with the square brackets, an array will be automatically generated, and it will be $_POST['MySelection'][0], $_POST['MySelection'][1] and so on. You can loop on it with a the usual foreach.

Related

PHP $_POST array print_r

I have a general question. I wrote the below code to add an array of arrays to the $_POST variable. I know the post variable is an array too. So, after adding my multidimensional array to the post variable one by one, I tried to print_r the data to view it but, only one array would print out.
why is it that only one array would print out?
$x = 0;
for($x; $x < count($return_auth); $x++){
$_POST = $return_auth[$x];
}
print_r($_POST);
Although nerdlyist answer is absolutely right, but I think it is not the right way, in short, you are modifying $_POST variable and since $_POST variable has a meaning attached to it that it contains all the parameters sent in that POST request. If you overwrite it that change will be affected throughout your application and other modules running in your application will see an additional post parameter which is not actually sent in that request in $_POST array which is not right IMO.
What you are doing is overwriting post. Based on what you have here you could do something like this:
$_POST[return_auth] = $return_auth;
Unless you have a reason to loop an array to create an array...
use this in your for loop
$_POST[] = $return_auth[$x];
Edit
this will work better
$_POST['something' . $x] = $return_auth[$x];
now you can access to (foo) for example
$_POST['somethingfoo'];

What is the proper way to clear super-global variable in PHP? [duplicate]

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.

How get size_of $_GET

I want to get the number of values that were submitted via my $_GET. I'm going to be using a for loop and every 7 are going to be saved to a class. Does anyone know how to find the Size_of the $_GET array? I looked through this info $_GET Manual, but don't see what I'm looking for.
This is a code snippet that I started in the class that I go to after the submit.
for($i=0;$i<$_GET<size>;$i++) {
$ID = $_GET["ID"][$i];
$Desc = $_GET["Desc"][$i];
$Yevaluation = $_GET["Yevaluation"][$i];
$Mevaluation = $_GET["Mevaluation"][$i];
$Cevaluation = $_GET["Cevaluation"][$i];
$Kevaluation = $_GET["Kevaluation"][$i];
$comment = $_GET["comment"][$i];
//saving bunch to class next
}
$_GET is an array. Like any other array in PHP, to find the number of elements in an array you can use count() or its alias sizeof().
count($_GET["ID"])
could work. However, then you have to be sure that each index contains the same number of elements.
More secure would be
min(count($_GET["ID"]), count($_GET["Desc"]), ...)
With array_map this can probably be shortcut to something like:
min(array_map(count, $_GET))
Try thinking through the last one, if it seems difficult to you. It's called functional programming and it's an awesome way to shortcut some stuff. In fact array_map calls another function on each element of an array. It's actually the same as:
$filteredGet = array();
foreach ($element in $_GET) { // this is the array_map part
$filteredGet[] = count($element);
}
min($filteredGet);
Even better would be a structure where $i is the first level of the array, but I think this is not possible (built-in) with PHPs $_GET-parsing.

Is this a reliable way to access options from a select element in PHP?

I have this select input in my form that I want to access via PHP.
<div data-role='fieldcontain'>
<label for='fruits' class='select'>Favorite Fruits</label>
<select name='fruits[]' id='fruits' multiple='multiple' data-native-menu='false'>
<option value=''>Favorite Fruits</option>
<option value='1' selected='selected'>Apple</option>
<option value='2' selected='selected'>Banana</option>
<option value='3' selected='selected'>Cherry</option>
</select>
</div>
By setting the name of the select element to "fruits[]", this works:
// |$fruits| is an array
$fruits = $_POST['fruits']
However, I am concerned about cleaning data from the form. Feeding post data into an array sounds insecure. What if, for instance, someone changes the select element into a text input element via Firebug and inputs malicious code into my program? I never call htmlspecialchars.
Are my security concerns valid? Why or why not?
They are valid indeed, if the data comes from the user input you need to sanitize it first.
In this case, a user can easily break your HTML or, even worse, inject some malicious XSS attack.
You need to sanitize the values, htmlspecialchars is enough in this case.
Nevermind, I understood you were populating the HTML select tag with options from user input, but this is not the case. PHP will only accept strings or arrays in POST data, so you need to make sure the data coming in is compatible with what you want to do with it. One possible solution would be to white-list the submitted values, functions like array_intersect might be useful here, for instance:
$allowed_fruits = array('Apple', 'Banana', 'Cherry');
$fruits = array_intersect($allowed_fruits, $_POST['fruits']);
This way, if the user submits "Strawberries" it will be ignored on the $fruits array.
You might also want to make sure that the array isn't multidimensional, like this:
if (count($_POST['fruits']) != count($_POST['fruits'], COUNT_RECURSIVE))
{
// array is multidimensional, do not process
}
This of course, depends on your usage of the data but the white-list approach is always the most secure.
Your code should be validating whether user input is in the expected format (isset, is_array, ...) and properly escaping it before sending it to the database, html output, logs, wherever else. Fundamentally there is very little difference in here between a user entered string and user entered array of strings.
Use mysql_real_escape_string (or even better PDO) to work with the database, htmlspecialchars to work with HTML output.
That is the correct way to get the values, however, you are right to worry. You receive the values the way you suggest, then you use an appropriate method of sanitation: htmlspecialchars for displaying, mysql_escape for inserting into your DB, etc. You'll need to do that for each element in your array, but only at the time you're going to use it.

Using extract

I'm new to OOP and want to revamp this function to get rid of using globals.
function CatchListing() {
$parseform = array('itemnum','msrp','edprice','itemtype','box','box2','box25','box3','box4','box5','box6','box7','itemcolor','link');
foreach ($parseform as $globalName) {
$GLOBALS[$globalName] = mysql_real_escape_string($_POST[$globalName]);
}
}
I was told to use array_map & then extact, but I am not sure of how to structure this.
function CatchListing() {
$_POST['listing'] = array_map('mysql_real_escape_string', $_POST);
$nst = extract($_POST['listing']);
}
(listing is the form name btw)
Thanks
Be VERY careful about using extract with externally inputted values as from $_GET and $_POST.
you're much better off extracting the values manually to known values.
It's far too easy for an extract from _GET or _POST to clobber existing variables.
There are so many things to say and Jonathan makes a very good start. Every time the user has the opportunity to play with your internal data and you don't check them, there is a huge "opportunity" (depends on the view..) that something goes wrong. Here is another approach on how to "maybe" get where you want to go:
<?php
function Sanitize($string){
return mysql_real_escape_string(trim($string));
}
function CatchListing(){
foreach($_POST as $key => $value) {
$key = Sanitize($key);
$value = Sanitize($value);
if($key && $value && !$GLOBALS[$key]){ /* prevent overwriting existing globals*/
$GLOBALS[$key] = $value;
}
}
}
global $nice;
$nice = "working";
CatchListing();
print_r($GLOBALS);
?>
To be honest, it still has not really anything to do with OOP and furthermore should be seen as a procedural approach. Personally I would use an additional and reusable function to "sanitize" the input, because you never know, if someday you want to change your database or the "escape" function and then you exactly know where to look for possible changes. Ah one more thing: Are you certain that you don't know all the possible names of all the variables you have to expect? Maybe you can predetermine them and put them in another array and check each user supplied argument with in_array.
To completely get rid of the usage of globals in your code, and also to make it much better overall, you can do something along these lines:
stop using $_POST, as it's a superglobal. When code needs values from superglobals, pass them as parameters
don't store values into $GLOBALS. If you need to return more than one value, consider returning an object or an array
Here's how I think I would modify your code to improve it:
function CatchListings($listings) {
$filteredListings = array_map('mysql_real_escape_string', $listings);
//I assume you only need the values in the array in the original snippet,
//so we need to grab them from the parameter array and return only that
$requiredListings = array();
$requiredKeys = array('itemnum','msrp','edprice','itemtype','box','box2','box25','box3','box4','box5','box6','box7','itemcolor','link');
foreach($requiredKeys as $key) {
$requiredListings[$key] = $filteredListings[$key];
}
return $requiredListings;
}
To use this function, you simply do $result = CatchListings($_POST);. Same result, no globals used.
There is one thing to consider, though. It may not be best possible form to just pass a randomly filled array (ie. $_POST) to the function, and expect it to contain specific keys (ie. $requiredKeys array). You might want to either add logic to check for missing keys, or process the post array before passing it.

Categories