PHP Type Juggling

Explanation on PHP type Juggling with an example

In this blog we will look at how PHP Type Juggling works and how they are used to bypass restrictions and for exploitation with a example of HTB box called Ransom

PHP Type Juggling

PHP is a dynamically typed language. This means that variable types are checked while the program is executing. Dynamic typing allows developers to be more flexible when using PHP. But this kind of flexibility sometimes causes unexpected errors in the program flow and can even introduce critical vulnerabilities into the application.

This means that variable types are checked while the program is executing. Dynamic typing allows developers to be more flexible when using PHP. But this kind of flexibility sometimes causes unexpected errors in the program flow and can even introduce critical vulnerabilities into the application. In short, if PHP has loose comparison i.e '==' then it get confused and treats different elements as same. For example, it can treat integer as string.

Type Comparisons

To better understand how we exploited PHP Type Juggling to bypass the login. First we need to understand comparison inside PHP. The PHP language consist of two types of comparisions.

  • Loose Comparison: "=="

  • Strict Comparison: "==="

In Loose Comparison if the PHP tries to compare two objects of different types such as one is string and another is integer while having the same value, the it will result in a 'True'. But in the Strict Comparison, both type and value of two objects must be equal otherwise it will result in a 'False'. Let's take a deeper look with and example. On the Linux type -> php -a to spawn a interactive PHP prompt.

First we will take a look at how Loose Comparison works.

In the above statement there are three examples of how loose comparison '==' works. The above code snippet compares two values and print "Success" if the conditions are met.

In the first example:

if ("1" == 1) echo "Success";

The php compares uses loose comparison '=='. In which it compares the string "1" and the integer 1 that resulting in Success because it didn't checked if both objects has same values.

In the third example:

if ("1" == true) echo "Success";

The PHP also gets confused on comparing anything with boolean as 'True'. The PHP Type Juggling we exploited for initial foothold followed this logic.

Now we take a look at how Strict Comparison works.

Now the code above is using strict comparison '==='.

In the first example:

if (1 === 1) echo "Success";
if ("1" === "1") echo "Success"

It compared the type and value of the objects. Both were same so we got a "Success".

In the second example:

if ("Hi" === "Hey") echo "Success";
if (1 === 2) echo "Success";

Even though both the objects were string. It did compare the values.

In the third example:

if (1 === true) echo "Success";
if ("1" === true) echo "Success";

By using the strict comparison. It doesn't get confused when we compare an object with a boolean value.

As we've seen that the loose comparison '==' is very dangerous that can lead to authentication bypass or RCE vulnerability. It is highly advised that we should always use '===' instead of '=='.

Example and Source Code Analysis

Now in this we will look at a sample php code that is vulnerable to PHP Type Juggling. This is from a HTB machine called Ransom. To solve this machine, refer the blog from the below link to exploit it using the PHP Type Juggling. I prefer you first go through the below write-up to understand better.

pageHackTheBox - Ransom

Now moving towards source code analysis.

In the below is the PHP code snippet from the vulnerable machine that gave us the authentication bypass via Type Juggling.

public function customLogin(Request $request)
    {
        $request->validate([
            'password' => 'required',
        ]);

        return $request;

        if ($request->get('password') == "UHC-March-Global-PW!") {
            session(['loggedin' => True]);
            return "Login Successful";
        }
  
        return "Invalid Password";

In the if statement we can see the comparison between the hard-coded credentials that is a string and the value of the 'password' parameter using the loose '==' comparison. In the burp request we've use boolean to bypass this comparison.

"password":true

The comparison result will be true and we will get access. We can see the behind the scenes of the functions using the php -a on terminal.

This could've not worked if try to use random integer or string.

In this we've used random integer and strings to test. This doesn't result in success because at least values of the two objects must be same. So in this case, random password bruteforce could not have worked. So when there is a login functionality we can try to bypass it with boolean based Type Juggling.

Thank your for reading 😉

Last updated