Challenge : trouble at the spa

Énoncé :

I had this million‑dollar app idea the other day, but I can’t get my routing to work! Can you navigate me to the endpoint of my dreams?

Une application React obfusquée est hébergée sur GitHub Pages :
https://ky28060.github.io/

Le dépôt source complet est fourni.

1. Analyse :

Sources :

Fichier Extrait contenu
src/main.tsx <Route path="/flag" element={<Flag />} />
src/Flag.tsx {'bctf{test_flag}'} (ou la chaîne chiffrée en prod)
src/Header.tsx <a href="/flag">Flag</a>
  • Le router React comporte bien une route interne /flag.

  • Le composant Flag affiche simplement le flag.

  • Le lien du Header est un <a> traditionnel : sur GitHub Pages cela déclenche une requête vers /flag → 404.

Déduction : pour voir le flag il suffit d’appliquer la route à chaud, sans recharger la page.

Pourquoi le clic normal échoue ?

  • GitHub Pages sert uniquement des fichiers statiques.
    Toute URL différente de / cherche un fichier réel et renvoie 404.

  • Tant que l’application est déjà chargée, React Router gère la navigation uniquement via l’History API.

3. Exploitation :

Dans F12, exécuter les deux commandes History API :

```js
// change l’URL SANS rechargement
history.pushState({}, '', '/flag');
// avertit React Router
dispatchEvent(new PopStateEvent('popstate'));
```
Instruction Effet
pushState Ajoute une entrée /flag dans l’historique sans recharger la page.
PopStateEvent Émet manuellement l’évènement capté par React Router ; celui‑ci rend la nouvelle route.

Le flag s’affiche en haut de la page !

4. Extraction « offline » :

Il est aussi possible de télécharger le bundle index-*.js, de repérer la table de chaînes et le décodeur RC4 généré par javascript‑obfuscator, puis de déchiffrer l’entrée contenant le flag – mais la méthode History API est plus rapide pendant le CTF.

5. Flag :

bctf{r3wr1t1ng_h1st0ry_1b07a3768fc}