Broad Network


PHP Array Security Risks and Prevention Explained

PHP Cheat Sheet and Prevention Explained - Part 5

Foreword: In this part of the series, I explain PHP array security risks and how to prevent them.

By: Chrysanthus Date Published: 29 Jan 2019

Introduction

This is part 5 of my series, PHP Cheat Sheet and Prevention Explained. In this part of the series, I explain PHP array security risks and how to prevent them.

Risks are weaknesses from PHP or from you the programmer, that you may ignore; and attackers (hackers) would take advantage of.

The count() Function
The syntax for the count function is:

    int count ( mixed $array_or_countable [, int $mode = COUNT_NORMAL ] )

I talk here only about the problems related to the first argument. I will talk about any problem related to the second argument some other time.

The count function returns the number of elements in the array or the number of certain things in an object (to talk about the things later).

If the $array_or_countable is null, the function returns zero. If the array is empty, you will also have zero. Solution: always check if the variable is an array, before you count the number of elements, with code like:

    $arr = array();
    if (is_array($arr))
        echo 'it is array';

If $array_or_countable is neither an object nor an array, the count() function returns 1. If there is only 1 element in the array, the function still returns 1. Solution: always check if the variable is an array, before you count the number of elements.

The array_push() Function
The problem with the array_push() function is that you may end up pushing into something that is not an array; a string for example. Try  the following code:

<?php

    $str = 'This is it.';

    array_push($str, 'again');

    echo $str;

?>

I tried the code and I had:

    Warning: array_push() expects parameter 1 to be array, string given in C:\Apache24\htdocs\temp.php on line 5
    This is it.

There is a warning message; no fatal error; the string received nothing; the program continues to run, possibly with wrong results.

Solution: always check if the first argument to the array_push() function is an array, before you push anything into it.

The array_pop() Function
The syntax for the array_pop() function is:

    mixed array_pop ( array &$array )

This function returns the value of the last element of array. If array is empty (or is not an array), NULL will be returned.

The problem here is that NULL will be returned, when the argument is not an array and you would not be able to determined, if it was NULL from an empty array or from a wrong argument.

Solution: always check if the argument to the array_pop() function is an array, before you pop anything off it. Also use the identity operators (=== or !==) to know if NULL or the value of 0 was returned.

The current() Function
The syntax for the current function is:

    mixed current ( array $array )

This function returns the current element in the array. If the internal pointer points beyond the end of the elements list or the array is empty, current() returns FALSE.

FALSE is a valid value of an element in an array. The end of an array and the result of calling current() on an empty array are indistinguishable from a boolean FALSE element.

Solution: do not use current() to determine if an array is empty or to determine the end of the array.

The next() Function
The syntax for the next() function is:

    array next($array)

This function returns the array value in the next place that's pointed to by the internal array pointer, or FALSE if there are no more elements.

Since false is a valid value for the element of an array, do not use next() to determine the end of an array. Only use it to move forward.

The prev() Function
The syntax for the prev() function is:

    array prev($array)

This function returns the array value in the previous place that's pointed to by the internal array pointer, or FALSE if there are no more elements.

Since false is a valid value for the element of an array, do not use prev() to determine the beginning of an array. Only use it to move backward.

The end() Function
The syntax for the end() function is:

    mixed end($array)

The function returns the value of the last element or FALSE for empty array.

FALSE can also be the value of the last element of the array.

Solution: To determine if the array is empty, use the count function. You must not necessarily use the end() function to read the value of the last element. Use it only to go to the last element and then use the key() and current() functions to read the key and value respectively.

The reset() Function
The syntax for the reset() function is:

    mixed reset($array)

The function returns the value of the first array element, or FALSE if the array is empty.

FALSE can also be the value of the first element of the array.

Solution: To determine if the array is empty, use the count function. You must not necessarily use the reset() function to read the value of the first element. Use it only to go to the first element and then use the key() and current() functions to read the key and value respectively.

Keys

Use of the next() and prev() Functions
Use of these functions as in:

    while (key($fruitColor))
        {
            echo key($fruitColor), ' => ', current($fruitColor), '<br>';
            next($fruitColor);
        }

AND

    while (key($fruitColor))
        {
            echo key($fruitColor), ' => ', current($fruitColor), '<br>';
            prev($fruitColor);
        }

Use of the key() function here, assumes that no key is zero or false or null or the empty string.

Solution. If any of these values is a key, then use the foreach construct to iterate; do not use this "while" scheme.

Creation of an Array
You can create an array by declaring without assignment, as follows

    $arr;

It is not clear if this variable holds an array or a scalar or some other variable. So, you the programmer can easily assign some other value to it down in the program. Then when you need the array, you get maybe a string, which in one circumstance, would behave like an array.

Prevention: Develop the habit of initializing your PHP variables during declaration. To know if a variable is in use up in the program, use the PHP predefined isset() function. Or, do not use this method of creating array, at all.

Another way to create an array, is as follows:

    $arr[] = value;

A problem here, is that, if $arr already had some elements, value will be added with the index that is 1 higher the highest index that was in the array. If no index was there, then the index given would be 0.

Prevention: How can you create an array that already has elements? Use the isset() function to know if the array is already in use, up in the program. If it is already in use, choose another name for the array. Or, do not use this method of creating array, at all.

The [] does not have to be empty when creating an array. You can create an array this way with some other index, other than 0. You may end up over-writing the value of some other element, which was already there. Or, you may actually add a new element (which is not bad). If $arr were a string, you would end up modifying the string. Try the following code:

<?php

    $str = 'word';

    $str[1] = 'avatar';

    echo $str, '<br>';

?>

The output is:

    ward

Imagine the damage this would cause if $str were a password, because you tried to create an array, this way.   

Prevent this by first checking if the variable is already in use, with the isset() function. Or, do not use this method of creating array, at all.

New Index
When you delete elements from an array, there is no re-indexing. When you add a new index to the array, just by adding a value (no key specified), the new index is the largest index before, plus 1. Assume that you had an array with the largest index, 12 and you delete the element, implying that there is no more index of 12. If you now add a value (without index) to the array, the new index would be 13. This is not usually a problem.

Occasionally you will need re-indexing after deleting elements. Use the array_values() function as in the following code:

<?php

    $arr = array(0=>'aa', 1=>'bb', 2=>'cc', 3=>'dd', 4=>'ee');

    unset($arr[2]);
    unset($arr[4]);

    foreach ($arr as $key => $value)
        echo $key, ' => ', $value, '<br>';

    array_push($arr, 'ff');

    echo '<br>';

    foreach ($arr as $key => $value)
        echo $key, ' => ', $value, '<br>';

    $arr = array_values($arr);

    echo '<br>';

    foreach ($arr as $key => $value)
        echo $key, ' => ', $value, '<br>';

    array_push($arr, 'gg');

    echo '<br>';

    foreach ($arr as $key => $value)
        echo $key, ' => ', $value, '<br>';

?>

The unset() function deletes an element. Reading the value of the deleted element, using the key, returns NULL.

The output is:

    0 => aa
    1 => bb
    3 => dd

    0 => aa
    1 => bb
    3 => dd
    5 => ff

    0 => aa
    1 => bb
    2 => dd
    3 => ff

    0 => aa
    1 => bb
    2 => dd
    3 => ff
    4 => gg

Read the code (program) to appreciate the output.

Reading the Value of an Array Element
You use a key (index) to read the value of an element; if the element exists, the reading returns the value. If the element has been deleted, the reading returns null. However, null is a valid value in PHP. The value of an element can actually be null. 0, "" and false can be evaluated as null later in the program

Solution: You should know in advance, the different possible values that an element can have. When you read the value, test for null with the === (or !==) operator.

Non-Consecutive Indices
Non-consecutive indices is usually not a problem. However, when it is necessary, do re-indexing.

Negative Indices
Nobody can work with negative indices as well as he/she can work with positive indices. Use negative indices only when you have to, such as in scientific work.

Types and Index
A float as index is made the integer by truncating the decimal part. You should convert the float to integer first, before you use it as array key index; otherwise you may have an algorithm related to the array, later in the program, that you will not be able to explain.

A string such as '+8' or '08', which would normally be casted to an integer, is not converted to the integer. You should convert any string you want as integer, to integer first, before you use it as array key index; otherwise you may have an algorithm related to the array, later in the program, that you will not be able to explain.

A key of Boolean true is converted to 1 for an index. A key of Boolean false is converted to 0 for an index. You should convert any Boolean value you want as integer, to integer first, before you use it as array key index; otherwise you may have an algorithm related to the array, later in the program, that you will not be able to explain.

A null value is converted to the empty string, "" for an index. Do you really want to use an empty string as key? Solution: If you really must use an empty string as key, then give the key a string value, such as "nn" or "nullKey".

An array or object cannot be used as a key. Doing so will result in a warning: Illegal offset type. This is not a fatal error which stops the program. The array element is ignored and the program continues to run. Ignoring an element leads to NULL for the value. Solution: Do not use an array or object as key.

Bare Words as Keys
You should use word keys in quotes, but within double quotes, you should use them as bare words. Used of bare words, conflict with current constants and constants to come.

Solution: Always use word keys in quotes. If you are to use it in a double quoted string, separate the string, isolating the array key variable as in the following code:

<?php

    $arr = array('one' => "aaa", 'fruits' => "oranges", 'three' => "ccc");

    echo "I need some " . $arr['fruits'] . " after meal.";

?>

In this way, you always use word keys in quotes.

Re-indexing and Maintaining String Keys
Note that with the use of the array_values() function, all string keys are replaced with integers. If you really want to do re-indexing and preserve the keys, then use the array_slice() function as in the following code:

<?php

    $arr = array(0=>'A', 'aa' => 'woman', 1=>'B', 2=>'C', 'bb' => 'man', 3=>'D', 4=>'E');

    unset($arr[2]);
    unset($arr[4]);

    foreach ($arr as $key => $value)
        echo $key, ' => ', $value, '<br>';

    array_push($arr, 'F');

    echo '<br>';

    foreach ($arr as $key => $value)
        echo $key, ' => ', $value, '<br>';

    $arr = array_slice($arr, 0);

    echo '<br>';

    foreach ($arr as $key => $value)
        echo $key, ' => ', $value, '<br>';

    array_push($arr, 'G');

    echo '<br>';

    foreach ($arr as $key => $value)
        echo $key, ' => ', $value, '<br>';

?>

The output now is:

0 => A
aa => woman
1 => B
bb => man
3 => D

0 => A
aa => woman
1 => B
bb => man
3 => D
5 => F

0 => A
aa => woman
1 => B
bb => man
2 => D
3 => F

0 => A
aa => woman
1 => B
bb => man
2 => D
3 => F
4 => G

You slice from the beginning to the end of the array.

That is it for this part of the series. We stop here and continue in the next part.

Chrys


Related Links

Basics of PHP with Security Considerations
White Space in PHP
PHP Data Types with Security Considerations
PHP Variables with Security Considerations
PHP Operators with Security Considerations
PHP Control Structures with Security Considerations
PHP String with Security Considerations
PHP Arrays with Security Considerations
PHP Functions with Security Considerations
PHP Return Statement
Exception Handling in PHP
Variable Scope in PHP
Constant in PHP
PHP Classes and Objects
Reference in PHP
PHP Regular Expressions with Security Considerations
Date and Time in PHP with Security Considerations
Files and Directories with Security Considerations in PHP
Writing a PHP Command Line Tool
PHP Core Number Basics and Testing
Validating Input in PHP
PHP Eval Function and Security Risks
PHP Multi-Dimensional Array with Security Consideration
Mathematics Functions for Everybody in PHP
PHP Cheat Sheet and Prevention Explained
More Related Links

Cousins

BACK NEXT

Comments