PHP — Type Juggling
Type Juggling it’s a kind of bug that occurs only on PHP, mainly due to the way the language “compares” one thing to another.
In PHP there’re a pair of operators that, although look similar, they do perform different tasks, those are ==
and ===.
Double equals essentially evaluate if the variable, or whatever being compared, is empty or not. We can see that on the first condition, which “verifies” if $txt
is really empty or not. The result obviously gonna be True
since $txt
is not empty at all.
However, there’s another way to do that, and that is with double equals. Take a look at the second comparison which basically checks if $txt
is equals to nothing, or “empty” in another words, if it really is, is gonna echo Empty!!
if it’s not, well… True.
However, double equals might be a problem, since the user can juggle it. Bbecause ==
just checks the content of what’s being evaluated, not its type. That might sound confusing, but let’s go one step at a time.
First, let’s understand how it work the assignment of a Boolean to a variable. When we assign False
to $txt
and print it, we see that it actually prints nothing at all. On the other hand, we can see that if we assign True
the echo outputs is 1.
That’s been said, let’s see how someone could potentially trick a comparison mechanism which use double equals.
Imagine a condition that checks whether a password is the right one or not. On the first case, we assign to the $password
variable thepass123
value. As a result, the condition is not met and consequently doesn’t print Access Granted.
But if we assign True
to $password
and repeat the comparison, we actually succeed, because true will always result in true.
That happens, due the fact that double equals only check the content of the variable being compared with something else, but true will always result in true.
That could lead to some bypass depending on the application functionaity.
Let’s take a look at this snippet of code from base box.
if (!empty($_POST['username']) && !empty($_POST['password'])) {
require('config.php');
if (strcmp($username, $_POST['username']) == 0) {
if (strcmp($password, $_POST['password']) == 0) {
$_SESSION['user_id'] = 1;
header("Location: /upload.php");
} else {
print("<script>alert('Wrong Username or Password')</script>");
}
} else {
print("<script>alert('Wrong Username or Password')</script>");
}
It’s basically checking, with strcmp
, if the provided username
and password
“equals” the ones stored at theconfig.php
file. If that comparison results in 0
then the “ifs” are satisfied.
That could easily be bypassed by providing an empty array for username and password.
Then we successfully bypass the login form.
In case of comprisons, the best approach is to implement it in a strict way, that’s why PHP has triple equals, which compares both data
and type
to whatever is being compared.