Broad Network


PHP String Security Risks and Prevention Explained

PHP Cheat Sheet and Prevention Explained - Part 4

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

By: Chrysanthus Date Published: 29 Jan 2019

Introduction

This is part 4 of my series, PHP Cheat Sheet and Prevention Explained. In this part of the series, I explain PHP string 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 strpos() function
This function finds the position (index) of the first occurrence of a substring in a string. It returns false, if the needle was not found, but it can also return 0 if the needle was found at index 0. The problem is that, you can test the return value for false, when 0 was returned, or you can test for 0 when false was returned. Either way, your test is wrong and your programming progresses wrongly. Attackers (hackers) like to take advantage of this.

Solution: You should know whether you are testing for no-needle-found or for needle found at index 0. For the first case, you use === and false; for the second case you use === and 0 as the following code illustrates:

<?php

    $str = 'A Star Wars Lightsaber looks like a multipurpose weapon for the future.';

    $substring = 'something else';
    $ret = strpos($str, $substring);
    if ($ret === false)
        echo 'not found', '<br>';

    $substring = 'A';
    $ret = strpos($str, $substring);
    if ($ret === 0)
        echo 'found at index 0', '<br>';

?>

The output is:

    not found
    found at index 0

If you are looking for not-found or index 0 as well, which is an unlikely occurrence, then use the following if-structure:

    if ($ret == false)
        echo 'found at index 0 or found nothing', '<br>';

The == operator considers false and 0 to be the same, independent of the types of the two operands; while the === operator compares both values and types of operands.

The strrpos() Function
This function finds the position (index) of the last occurrence of a substring in a string. This function has the same weaknesses as the above function, and has the same solution.

The strlen() Function
This function returns the length (number of bytes) of the string on success, and 0 if the string is empty. The weaknesses and solution are similar to the above.

The substr() Function
This function returns the extracted part of a string; or false on failure, or an empty string. The == operator compares false and an empty string, "" the same, while the === operator compares both value and type. The weaknesses are similar to the above and the solution is similar.

The substr_replace() Function
The syntax of this function is:

    mixed substr_replace ( mixed $string , mixed $replacement , mixed $start [, mixed $length ] )

This function returns a string if the first argument is a string or returns an array if the first argument is an array. You need to first test if the returned value is a string or if it is an array before you start testing the content of the string or contents of the array. You may have to make use of the is_string() and is_array() functions. You continue with a solution similar to the above (to test the individual array values).

The str_replace() Function
The syntax of this function is:

    mixed str_replace ( mixed $search , mixed $replace , mixed $subject [, int &$count ] )

The weaknesses, except one, for this function are similar to those of the substr_replace() function. The solution is similar.

However, because str_replace() replaces left to right, it might replace a previously inserted value when doing multiple replacements. I am still to come across a solution to this particular problem. If you know it, register and give it as a comment, below.

The explode() Function
The syntax to this function is:

    array explode ( string $delimiter , string $string [, int $limit = PHP_INT_MAX ] )

This function returns an array of strings, each of which is a substring of string, formed by splitting it on boundaries, formed by the string delimiter.

If delimiter is an empty string (""), explode() will return FALSE. If delimiter contains a value that is not contained in string and a negative limit is used, then an empty array will be returned, otherwise an array containing substrings will be returned.

Prevention: do not forget to test for false, array and array contents.

Use of Indexing to access Characters in a String
Use of indexing to access characters in a string, has some issues.

Quotation from the PHP Manual: "Writing to an out of range offset pads the string with spaces. Non-integer types are converted to integer. Illegal offset type emits E_NOTICE." Try the following code:

<?php

    $var = 'I love';
    $var[7] ='y'; $var[8] ='o'; $var[9] ='u';
    echo $var, '<br>';

    $num = '3.8';
    $num[4] ='8';
    echo $num, '<br>';

?>

The output is:

    I love you
    3.8 8

In the first result line, a single space was padded after the first string segment, luckily to our advantage. We were not lucky for the second result line. Instead of having 3.88 we had 3.8 8, with the gap between the 8s. The solution is just to be very carefull when you are coding.

Caution when escaping ' and " for interpolation
Try the following code:

<?php

    $var1 = "This is John's book";
    $varA = 'The quotation, "This and That", is from the book.';
    $var2 = "The quotation, \"This and That\", is from the book.";
    $varB = 'This is John\'s book';
    $var3 = "This is John\'s book";
    $varC = 'The quotation, \"This and That\", is from the book.';

    echo $var1, '<br>';
    echo $varA, '<br>';
    echo $var2, '<br>';
    echo $varB, '<br>';
    echo '<br>';
    echo $var3, '<br>';
    echo $varC, '<br>';

?>

The output is:

    This is John's book
    The quotation, "This and That", is from the book.
    The quotation, "This and That", is from the book.
    This is John's book

    This is John\'s book
    The quotation, \"This and That\", is from the book.

From the output, we see that, if you want a single quote delimited by double quotes, just type the single quote directly, as it does not conflict with the delimited double quotes - that is alright. If you want a double quote delimited by single quotes, just type the double quote directly, as it does not conflict with the delimited single quotes - that is alright.

If you want a double quote delimited by double quotes, escape the double quote, as it would conflict with the delimited double quotes - that is alright. If you want a single quote delimited by single quotes, escape the single quote, as it would conflict with the delimited double quotes - that is alright.

At this point, you would assume that whenever you want a quote within a string, you can just escape the quote. Well, PHP does not really work like that. The last two lines of the output, show that if you want a single quote, delimited by double quotes, and you escape the single quote, you will have the escaped sequence, \' at the output - wrong output. If you want a double quote, delimited by single quotes, and you escape the double quote, you will have the escaped sequence, \" at the output - wrong output.

The solution is just to take note of the exceptional qualities of the last two lines of the output.

Expansion of Expressions in a Double Quoted String
Try the following:

<?php

    $tha = 'that';

    $arr = array("stea" => "steal");

    class mny
        {
            public $mon = "money";
        }

    $obj = new mny();

    echo "All $tha is their effort to $arr[stea] my $obj->mon.";

?>

The output is:

    All that is their effort to steal my money.

Expressions in a double quoted string expand. Such a string (with expansions) can end up accidentally as a function; and who knows what an attacker would do with such a function. The prevention is:

- when you have the choice to use single or double quoted string, use single quoted string;
- assign the value of an expression to a scalar variable; then join the variables into a possibly single quote string with the dot operator. You end up with a longer code, but that is more secured. So, the above code is better written as:

<?php

    $tha = 'that';

    $arr = array("stea" => "steal");

    class mny
        {
            public $mon = "money";
        }

    $obj = new mny();

    $ste = $arr['stea'];
    $mo = $obj->mon;

    echo "All $tha is their effort to $ste my $mo.";

?>

See variable variable and complex variable, which follow, for more security risks, and solutions.

Variable Variable
$thirty (which expands in double quotes) from the following code segment is a variable variable.

    $age = 'thirty';
    $$age = 'for John';
    echo $thirty;

Other examples of variable variables are:

$$age
${$age}    //which expands in double quotes
$arr[age]    //which expands in double quotes, wrongly
${$myObject->num}    //which expands in double quotes

The variable variables scheme allows a program to change the variable of a value; normal programming allows the change of the value of a variable. Attackers (hackers) like to take advantage of such a feature. Solution: Do not code (use) the variable variabes scheme in your programming.

Variable Variable and Double Quoted String: Including variable variable expressions in double quoted strings, just complicates the problem from double quoted string, even more.

Complex Syntax and Double Quoted String
If you want an expression (simple or elaborated) to result in a value within double quotes, just enclose the expression with curly brackets. That works in many cases; however there are situations where it is problematic, as in the following code (try it);

<?php

    $great = 'fantastic';

    echo "This is {$great}.", '<br>';
    echo "This is ${great}.", '<br>';

?>

The output is:

    This is fantastic.
    This is fantastic.

but there is a problem with the second echo statement. The opening brace is after the $ symbol instead of being in front. Such an expression, in this situation, should return nothing (NULL) or create a fatal error (which would stop the program from running); however, the program works continuously. Hackers like this.

Prevention: Avoid using complex syntax (within double quotes). Assign the value of an expression to a scalar variable; then join the variables into a possibly single quote string with the dot operator. You end up with a longer code, but that is more secured.

Note: attackers (hackers) are always ready to take advantage of all the weaknesses mentioned above; some of which are from PHP and some of which are from you. So, always code in a way that prevents them from taking advantage.

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