Pwning PHP: Type Juggling
In PHP “==” is used to compare values of two variables, but like PHP the “==” comparison is also weird. When comparing a string and an integer using “==”, PHP will try to convert the string to an integer and then do the comparison. Let’s see how we can exploit it,
Now imagine a website with a hardcoded password (not a good idea )
if($_POST['password'] == "password")
What if we provide 0 (integer) as input? As the “password” string has no number in it, the condition will return true.
“abc” == int(0)
Here is a table of comparisons made by “==” and their results:
Now let’s take a look at some real-world bugs:
Authentication bypass in CMSMS:
As the checksum is compared loosely, we can set the checksum value as “true” or “0” to bypass the validation mechanism:
Laravel CSRF Protection Bypass:
if (Session::token() != Input::get('_token')) { throw new Illuminate\Session\TokenMismatchException; }
Researchers also found that 85% of the CSRF tokens start with a letter or zero, we can again exploit this by setting the CSRF token’s value as “0”. But we have to pass it as an integer, not as a string. We can make use of JSON to do this:
$.ajax("http:///sensitiveaction", { type: 'post', contentType: 'application/x-www-form-urlencoded; charset=UTF-8; /json', data: '{"sensitiveparam": "sensitive", "_token": 0}', });
What is the solution?
We can use “===” , the strict version of “==”. Here is the comparison table:
PHP type juggling is a difficult bug to exploit because even if you find a Type juggling bug you have to find a way to send the payload as an integer or a boolean , as HTTP parameters are always strings. Here are a few resources to learn more:
http://blog.laravel.com/csrf-vulnerability-in-laravel-4/
https://labs.mwrinfosecurity.com/blog/2014/04/11/laravel-cookie-forgery-decryption-and-rce/
http://php.net/manual/en/language.types.type-juggling.php