PHP's new input_filter does not read $_GET or

2019-01-23 16:50发布

问题:

In PHP 5.2 there was a nice security function added called "input_filter", so instead of saying:

$name = $_GET['name'];

you can now say:

$name = filter_input (INPUT_GET, 'name', FILTER_SANITIZE_STRING);

and it automatically sanitizes your string, there is also:

  • FILTER_SANITIZE_ENCODED
  • FILTER_SANITIZE_NUMBER_INT
  • FILTER_SANITIZE_EMAIL
  • FILTER_SANITIZE_URL

etc. so this is a very convenient security feature to use and I want to switch over to it completely.

The problem is... I often manipulate the $_GET and $_POST arrays before processing them, like this:

$_GET['name'] = '(default name)';

but it seems that filter_input does not have access to the changes in $_GET since it reads "INPUT_GET" which is of type int (?). It would be nice if I could get filter_input to read $_GET instead but:

$name = filter_input ( $_GET, 'name', FILTER_SANITIZE_STRING );

gives me the error:

Warning: filter_input() expects parameter 1 to be long, array given.

Can anyone think of a way that I could:

  • manipulate the source of INPUT_GET (whereever it is) so that I can change its values before filter_input can read them
  • get filter_input to read $_GET

ADDENDUM:


Rich asked: "Why are you changing the arrays anyway, surely you want them to be an input, rather than something you've programmatically inserted."

It is just a very convenient place to preprocess variables coming in, e.g. in order to:

  • set defaults (if $_GET['state'] = '' then $_GET['state'] = 'AL')
  • do manual processing (delete all spaces, etc.)
  • security (some of which will be done by filter_input now)

Then I know by the time I get the incoming variable, it is secure and valid. Of course I could copy the $_GET array to another array and process THAT array but that is just an unnecessary step since I $_GET is already a functioning array so it makes sense to do it with these system arrays that already exist.

回答1:

You could manually force it to read the arrays again by using filter_var and filter_var_array

$name = filter_var ( $_GET['name'], FILTER_SANITIZE_STRING );


回答2:

A handy way to do this without modifying the global array:

if (!($name = filter_input(INPUT_GET, 'name'))) {
    $name = 'default_value';
}

Or using the ternary operator:

$name = ($name = filter_input(INPUT_GET, 'name')) ? $name : 'default_value';


回答3:

If you are manually changing the array, surely you don't need to sanatise it anyway? Why are you changing the arrays anyway, surely you want them to be an input, rather than something you've programmatically inserted.

Perhaps more code/context would be helpful.



回答4:

As was suggested by Jrngs:

Skip programatically modifying the superglobal request variable and define and use new ordinary variables.

Not only it is way faster to create new variable than to access and modify value in associative array (array with string indexes), it is also generally a way better practice.

The whole point of filter_input function is to eventually REMOVE the usage of superglobal variables, since they are the single most dangerous point of all PHP scripts and most frequent cause of security vulnerabilities (for both XSS and SQL injections) as well as bugs and confusion, especially in large projects.

For example, the $_GET and $_REQUEST variables should return the same value for the same key, however:

.../?var=1
var_dump($_GET['var']); ---> string '1' (length=1)
var_dump($_REQUEST['var']); ---> string '1' (length=1)
$_GET['var'] = 2;
var_dump($_GET['var']); ---> int 2
var_dump($_REQUEST['var']; ---> string '1' (length=1)

Not to mention superglobal variables barely make any sense in object oriented code.

Therefore should the filter_input function access the $_GET/$_POST/$_REQUEST superglobal variables, that would completely defeat the point of this function. And you definitely SHOULD NOT use the suggested filter_var function for this:

filter_var($_GET['var'],FILTER_SANITIZE_STRING); ---> JUST NO!

The filter_var function was created in order to provide filtering/sanitizing functionality for non-request variables as well, not for this kind of "hack". What you're doing is you essentially take filters from filter_input function, which was originally created to provide better and safer access to request data, bypass the function itself completely, access request data the very way filter_input was created to replace, and apply the filters provided by filter_input on the request data. And that's just plain wrong. :)



回答5:

The INPUT_GET bit is just an identfier (number) telling PHP that it needs to get the value from $_GET.

If you want to use filter_input on the entire array, you need to loop through it, send each array key to filter_input, and put the result back in $_GET.

It'll probably be just as easy to just write a function that does the sanitizing yourself, and that should also allow you to deal with arrays in arrays (it doesn't look like filter_input will do that). There are a couple of these sample functions in the PHP.net documentation comments, doing stuff like removing "magic quotes". See here for an example.



回答6:

PHP's new input_filter does not read $_GET or $_POST arrays. If you are overwriting Global's (like,$_GET,$_POST) then Don't go for filter_input. Instead use filter_var ( $_GET['name'], FILTER_SANITIZE_STRING ) by manually passing variable.