← Back to all posts

Writeups // Article

Room 404 | TryHackMe Room Writeup

A beginner-friendly walkthrough of Room 404, a TryHackMe web challenge about directory enumeration and an exposed Git repository.

Welcome to my writeup for the TryHackMe room Room 404, part of the Hacker Holidays series. This was a short web challenge that demonstrated how an exposed Git repository can reveal files a developer thought had been deleted.

Spoiler warning: This walkthrough reveals the room’s solution path, but the final flag is masked.

Room 404 header on TryHackMe

Exploring the Hotel Website

The room provided a link to the Byte Lotus Hotel website.

Byte Lotus Hotel website supplied by the room

The page looked polished, but none of its navigation links led anywhere useful. I checked the page source next in case it contained a hidden route, comment, script, or other clue. Apart from the visible page markup, there was nothing interesting there either.

Source code of the Byte Lotus Hotel landing page

With the obvious checks exhausted, the next step was to enumerate files and directories that were not linked from the page.

Finding the Exposed Git Repository

I ran DIRB against the site with its common.txt wordlist:

dirb http://<ipaddress>:8080/ /usr/share/dirb/wordlists/common.txt

The scan discovered a publicly accessible .git directory.

DIRB discovering the exposed .git directory

Opening the directory in the browser confirmed that directory listing was enabled. It exposed the usual Git repository structure, including HEAD, config, logs, objects, and refs.

Directory listing for the exposed Git repository

I explored these directories manually at first, but there was not much useful information in the plain-text files. The files under .git/objects/ were also not readable directly in the browser.

Browser attempting to open a file from the Git objects directory

That was expected: Git stores repository data as compressed objects rather than ordinary source files. Instead of inspecting each object individually, I downloaded the entire .git directory so Git could reconstruct and interpret the repository for me.

Downloading the Repository

I used wget recursively:

wget -r -np -R 'index.html*' http://<ipaddress>:8080/.git/

The options used here were:

  • -r to download recursively;
  • -np to prevent wget from following links into parent directories;
  • -R 'index.html*' to reject the directory-listing pages generated by the web server.

Once the download finished, I opened the recovered site folder in Visual Studio Code. Its Source Control view immediately recognized the Git metadata and showed three tracked files as deleted but not committed:

  • app.js;
  • index.html;
  • README.md.

Visual Studio Code showing three deleted files recovered from Git metadata

Opening the deleted README.md change revealed its previous contents, including the flag:

# Byte Lotus — Guest Experience Platform

Internal staging repository for the guest app and concierge personalization
service. Do not deploy this folder to production.

Staging flag (remove before launch): THM{[REDACTED]}

No complicated Git commands were necessary. Once the complete repository metadata was available locally, Visual Studio Code used it to show exactly what had been removed from the working tree.

Why the Exploit Worked

Deleting a file from a website does not remove it from the site’s Git history. The .git directory contains the objects and references Git needs to reconstruct tracked files and earlier versions of the project.

In this case, the web server exposed that directory and allowed every part of it to be downloaded:

Exposed .git directory
Repository metadata downloaded
Git reconstructs deleted files
README.md reveals the flag

This is why .git should never be deployed inside a publicly accessible web root. Blocking directory listings alone is not enough either; if the individual Git files remain reachable, an attacker may still be able to retrieve the repository.

Takeaways

Room 404 was simple, but it reinforced a useful web-enumeration workflow:

  • inspect the page and its source first;
  • enumerate unlinked files and directories when the visible site reaches a dead end;
  • recognize the standard structure of an exposed Git repository;
  • download the complete repository instead of trying to read individual Git objects;
  • check deleted and historical files for information that is no longer visible on the live site.

The main lesson is that version-control metadata can expose far more than the current contents of a website. Secrets removed from the working tree may still be recoverable until they are removed from the repository’s history and rotated.

And we’re done!

P.S. Apologies for the terrible screenshots quality. I’m currently experimenting with Linux Mint and Flameshot is outputting low-quality images for some reason. I miss ShareX already.