0%

AReactRouterTrick-b01lersCTF2025

Omar Mohamed
Thanks for sharing!

بِسْمِ اللَّهِ الرَّحْمَنِ الرَّحِيمِ

A React Router Trick - b01lersCTF 2025
Hello again and welcome to another writeup! It's Omar (aka Mushroom) and today we got some cool b01lersCTF ideas in web challenges. This time I was participating with lil L3ak team, such an amazing one with so much interesting people!
I've covered 2 challenges here, the second one is an easy one and the first got some spice!
Let's not waste any more time and dive right in.

Challenge 1: trouble at the spa

I l0ved this challenge's idea. I provided a detailed technical explanation ♥️
Challenge Describtion: I had this million-dollar app idea the other day, but I can't get my routing to work! I'm only using state-of-the-art tools and frameworks, so that can't be the problem... right? Can you navigate me to the endpoint of my dreams?
It has something to do with routing. Let's check the source code.
It was a simple app, no complicated logic, the main part is the following:
App.tsx has the main page, and Flag.tsx has the flag, it is shown that it is under the path /flag.
So I visited the challenge link https://ky28060.github.io/ and visited /flag, but got 404 Not Found...
I actually also visited its github repo and indeed there was no other pages, just index.html
There was a heavily obfisticated js file, spend some time on it but yielded me nothing (it's my bad though, I didn't beleive the author when he wrote 'Don't rev me :(')
rev
Now since the challenge is about routing (React Routing specifically), let's learn a bit about it.
What does react client-side routuing do? It allows navigation between pages without refreshing the browser, using JavaScript to dynamically update the content without the need to call the server again for a new page. Check that if you need more details
Since Flag.tsx is imported in the code, it’s bundled in the JavaScript and exists in the client-side app. The 404 error likely occurs because GitHub Pages isn’t configured correctly to handle client-side routes like /flag, instead returning a server-side error.
React Router, however, can still render the Flag.tsx component if we update the URL without triggering a full page reload. To solve this, open the browser’s developer console and run:
This changes the URL to /flag in the browser, prompting React Router to load the Flag component and display the flag, bypassing the server’s routing issue.
Now do
This detect URL changes and update the rendered component accordingly.

Let's explain this a bit more 🙂

Think of it as a normal page refresh but in client side instead of server side. Normal page reload or refresh calles the specific path from the backend, but as we just said.. it is in the client side, that's what the previos commands does:
  1. Update the URL without triggering a full page reload, making it seem like you navigated there.
  2. Fires a popstate event to tell React Router the history changed, so it checks the new /flag URL and renders the Flag component.
A popstate event is dispatched to the window every time the active history entry changes between two history entries for the same document. If the history entry being activated was created by a call to history.pushState() or was affected by a call to history.replaceState(), the popstate event's state property contains a copy of the history entry's state object. Read more
Flag
bctf{r3wr1t1ng_h1st0ry_1b07a3768fc}
That was a fun one! Now Let's end with an easy one!

Challenge 2: When

This challenge features a gambling web application where users try to win a flag by getting lucky with a timestamp-based hash.
It determines winning based on timestamps. The server takes the current time from the Date header of incoming requests, converts it to a Unix timestamp, and uses SHA-256 to hash it. If the first two bytes of the hash are both 0xFF (255), the user wins and receives the flag.

Key Challenge Components:

app.ts:
There was also a rate limit set to 60 requests / minute

Vulnerability

The key vulnerability is that the server accepts a custom Date header from the client:
This allows an attacker to send a specific timestamp that will generate a hash with the required pattern (two 0xFF bytes at the beginning).

Solution

The solution involves finding a Unix timestamp that, when hashed with SHA-256, produces a hash where the first two bytes are both 0xFF.
So I made the following script:
After running it I got: Sun, 20 Apr 2025 03:55:30 GMT. Just put it in a Date header and you get the flag!
flag
bctf{ninety_nine_percent_of_gamblers_gamble_81dc9bdb}

That's it! I hope you've learnt something or two, find me On X or Discord. See you in the next one! 🚀

You might also like