i PHP String comparison vulnerabilities – All things in moderation

PHP String comparison vulnerabilities

1. Bypass PHP ‘==’ and ‘!=’ comparison operators

‘==’ and ‘!=’ is the default comparison in other languages. But in PHP has two main comparison modes, lets call them loose (‘==’ and ‘!=’)
and strict (‘===’ and ‘!==’).

Consider 2 following table to see the strict in ‘===’ and the loose in ‘==’:

PHP Comparisons: Loose

PHP Comparisons: Strict

So PHP will do type juggling before compare using ‘==’ operator ( http://php.net/manual/en/language.operators.comparison.php )

Type juggling means If PHP decides that both operands look like numbers, even if they are actually strings, it will convert them both and perform a numeric comparison:

  • TRUE: “0e12345” == “0e54321”
  • TRUE: “0e12345” <= “1”
  • TRUE: “0e12345” == “0”
  • TRUE: “0xF” == “15”

Or if we comparing a string to a number, PHP will attempt to convert the string to a number then perform a numeric comparison:

  • TRUE: “0000” == int(0)
  • TRUE: “0e12” == int(0)
  • TRUE: “1abc” == int(1)
  • TRUE: “0abc” == int(0)
  • TRUE: “abc” == int(0)

For example bypass authentication using '==' and '!=' comparison operators

Consider following PHP code handling to check for valid user's token.

<php
        $token = "0e124656823434657657655654324342";
        if(isset($_COOKIE['token']) && $_COOKIE['token'] == $token) {
                // access to privilege area
        }
        else {
                // login require
        }
?>

or

<php
        $token = "0e124656823434657657655654324342";
        if(isset($_COOKIE['token']) && $_COOKIE['token'] != $token) {
                 // login require
        }
        else {
                // access to privilege area
        }
?>

So If we input to application $COOKIE[‘token’]=’0′. What happen next?

$COOKIE[‘token’] == $token (‘0e124656823434657657655654324342’ == ‘0’) will return TRUE
$COOKIE[‘token’] != $token (‘0e124656823434657657655654324342’ != ‘0’) will return FALSE

=> authentication passed.

Recommendations

Use === as your default comparison. Only reach for == if you really need it

2. Bypass PHP strcmp() function

strcmp is a function created to compare strings.

int strcmp(string $str1, string $str2);

  • Return <0 if $str1 < $str2
  • Return 0 if $str1 === $str2
  • Return &Gt;0 if $str1 > $str2

For example: Consider following PHP code handling to check for valid user's token.

<php
        $token = "0e37bd1f669d8bb5eae47ef80013e4d3d8287c11";
        if(isset($_COOKIE['token']) && strcmp($_COOKIE['token'], $token) === 0) {
                // access to privilege area
        }
        else {
                // login require
        }
?>

If we request with cookie token is an array to pass an array instead of a string to strcmp(), it will gives a warning (‘WARNING strcmp() expects parameter 2 to be string, array given on line number …!’) but the compare result return 0.

This request look like:

GET / HTTP 1.1
Host: example.com
Cookie: token[]=''
.....

=> $_COOKIE[‘token’] = array( 0 => “”);

strcmp(array( 0 => “”), “0a37bd1f669d8bb5eae47ef80013e4d3d8287c11”) will return 0.

=> authentication passed.

Recommendations

Don’t use this function to compare 2 variables which you don’t know types.

Perform type conversions to string using the cast (string) before put into strcmp().

References

https://www.owasp.org/images/6/6b/PHPMagicTricks-TypeJuggling.pdf

One Response

  1. Frederic August 22, 2017

Leave a Reply