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 ≫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
I agree: don’t use loose comparison.
But, your are wrong in your “vulnerability” sample.
Here an 3v4l: https://3v4l.org/VqDnL