InfoSec Write-ups

A collection of write-ups from the best hackers in the world on topics ranging from bug bounties…

Follow publication

HTB Challenge Write-Up: Juggling Facts

Code Review

Juggling Facts is a website featuring “not-so-spooky” facts about pumpkins. It is written in PHP, a loosely typed language. Given the challenge’s title, it most likely contains a Type Juggling vulnerability. Let’s dive deeper.

Upon reviewing the code, the flag can be retrieved by querying the database through the /api/getfacts endpoint. However, a few conditions must be met to access the code that interacts with the database.

if ( empty($jsondata) || !array_key_exists('type', $jsondata))
{
return $router->jsonify(['message' => 'Insufficient parameters!']);
}

if ($jsondata['type'] === 'secrets' && $_SERVER['REMOTE_ADDR'] !== '127.0.0.1')
{
return $router->jsonify(['message' => 'Currently this type can be only accessed through localhost!']);
}

Given these conditions, our payload must (1) be a JSON object containing a type field, and (2) ensure the type field's value is NOT a string equal to "secrets".

Sounds easy, right? But there’s a problem. To retrieve the database entry containing the flag, the type value must be a string equal to "secret". This directly conflicts with the second condition our payload must satisfy.

switch ($jsondata['type'])
{
case 'secrets':
return $router->jsonify([
'facts' => $this->facts->get_facts('secrets')
]);

// code omitted for brevity
}

We’re faced with two conflicting conditions that need to be met to retrieve the flag. The first condition uses strict comparison (===), so the second one, which uses a switch/case statement, must be loose, right? There’s one way to find out—Google it.

That confirms it! The official PHP documentation reveals that switch/case uses a loose comparison. This is a clear case of Type Juggling.

Local Testing

Since the code doesn’t include a type check, let’s consult PHP’s loose comparison table to determine which other data types can be compared to a string for the condition to be true.

According to the table, when a non-empty string is loosely compared with the boolean value true, the result will be true. Let’s confirm this by using the PHP interactive shell (type php -a in the terminal).

Exploitation

Now that we’ve confirmed we can use the boolean value true with a non-empty string to trigger Type Juggling, we can leverage this to match the first case of the switch/case statement, which happens to be the one that retrieves the flag.

Using curl, we’ll send the JSON payload {"type":true} to the /api/getfacts endpoint. Notice that the value true doesn’t have double quotes, so it will be parsed as a boolean.

This successfully retrieves the flag.

References

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

Published in InfoSec Write-ups

A collection of write-ups from the best hackers in the world on topics ranging from bug bounties and CTFs to vulnhub machines, hardware challenges and real life encounters. Subscribe to our weekly newsletter for the coolest infosec updates: https://weekly.infosecwriteups.com/

Written by Pat Bautista

I'm a software developer passionate about application security. I enjoy breaking applications to uncover weaknesses and then reinforcing them to be more secure.

No responses yet

Write a response