Monthly archives: August 2014

Comparing strings with == in PHP – potentially dangerous

Posted on August 31, 2014 Comments

I may be speaking the obvious to some with this post… but having seen plenty of code (including my own) doing comparisons using == where they probably should be using === and allowing PHP to just guess, I decided to write this up. I
had an issue where I kept trying to check a string against a variable that was setting itself zero – and it was coming up true. I didn’t understand why until I researched the issue further.

Considering the following code in pin.php; this is a very simple (dumb) PIN number checker; but with a bad mistake.

This code looks like it would be fine, but it has a huge security flaw. Do you see the issue here?

pin.php?PIN=12345 will not work.

pin.php?PIN=A123GA will not work

pin.php?PIN=J4YC1NK will work as expected

But what about just visiting pin.php with no input parameter? It will output:

“But WHY? $pin is set to zero if there was no input for good measure!” And herein lies the mistake: When it was set to zero, the data type was cast as numeric.

PHP then looked at the conditional statement and did a numeric comparison instead of a string comparison.

To understand how PHP treats strings when it automatically typecasts them, see this result from var_dump():

The output would be int(0); So our comparison was comparing zero to zero… ah, of course it would be true. This is what happens when PHP sees a string and typecasts it to an integer – you get a zero.

This problem can be avoided by using === for an exact comparison instead of the == operator. You can read about it here, it’s all conveniently documented.

Note that if $pin was not set to zero, then this wouldn’t be a problem in this example. $_GET variables are passed as strings, so setting it to zero (pin.php?PIN=0) will not work to accomplish the same thing. I’m not going to say that using == is horrible and that if you’re doing comparisons this way that your code is now easily exploitable. Chances are, that’s not the case. The above was ‘poorly written’ on purpose just to demonstrate the issue. PHP’s guesswork does a pretty good job, but this is just something to be mindful of while programming.