null
null

Reputation: 11879

Removing arrays from superglobals ($_GET, $_POST...)

In PHP it's possible to have arrays in $_GET, $_POST, $_COOKIE, $_FILES and $_REQUEST according to PHP documentation. The problem is that those come from user and I might get them instead of strings. For example, consider following snippet.

<?php
if (isset($_GET['hello'])) {
    echo 'Hello, ', htmlspecialchars($_GET['hello']), '.';
}
else {
    echo '<form action="?"><input name="hello"><input type="submit"></form>';
}

Looks OK? Well, as long you will not work will the URL it will work correctly. The problem is that hacker can try making $_GET['hello'] an array. If URL string looks like ?hello[]=something PHP will return error message

Warning: htmlspecialchars() expects parameter 1 to be string, array given in FILE on line 3

OK, who would enable in HTML errors in the production site (the other thing is error log...). But integers also are a problem - PHP is dynamically typed language, so it would accept easily code like '2' + 2. While yes, you can use (int) I have some old code which doesn't do that. If string comes from $_GET or $_POST it could be also array. Something like array('2') + 2 would cause fatal error of PHP.

Fatal error: Unsupported operand types in FILE on line 3

Now it's something that isn't acceptable because it would stop the script. I don't need arrays in those variables, but they annoy me. Is there any simple snippet which would remove arrays from those special variables. If I really would want an array, I could make copy of it before running the snippet.

Upvotes: 0

Views: 1230

Answers (3)

Sudhir Bastakoti
Sudhir Bastakoti

Reputation: 100195

Can you then do something like this:

foreach($_POST as $key => $val) {
    if(is_array($val)) {
        unset($_POST[$key]);
    }
}

Hope it helps in some sense.

Upvotes: 1

Corbin
Corbin

Reputation: 33457

I would check if it was a string before using it in a string context.

$name = (isset($_GET['name']) && is_string($_GET['name'])) ? $_GET['name'] : 'Unknown!';

Or:

if(isset($_GET['name']) && is_string($_GET['name']) {
    //do stuff
}

If you wanted to remove all arrays though:

foreach($_GET as $key => $val) {
    if(is_array($val)) {
        unset($_GET[$key]);
    }
}

Oops look like Sudhir already beat me to that part, but already had it typed... :)

Upvotes: 1

Steve Robbins
Steve Robbins

Reputation: 13812

You could use is_array() to check for such a thing.

if (is_array($_GET['hello']) // exit/error

or just display the form again

if (isset($_GET['hello']) && !is_array($_GET['hello']) {

As for someone inputting something like array('2') + 2 you don't need to worry much. It's already a string, therefor it won't be run as php script. However, depending on your scope is always a good idea to encode the information in a format best for you.

In you example, someone could inject HTML code into your get variable, causing the site to look different. Simple functions like strip_tags or htmlentities wouldn't hurt.

Upvotes: 3

Related Questions