Some vulnerabilities require careful crafting of payloads, hours of fuzzing, or chaining multiple weaknesses together. And then there's IDOR, where the "exploit" is literally changing a number in a URL. This challenge is a perfect introduction to why that simple action can be so devastating.

Skipping the Port Scan

For once, I didn't bother with nmap. The entire attack surface is the web application itself. Not every challenge needs every tool.

Directory fuzzing didn't reveal anything beyond what was already visible in the app. Time to actually use it.

Creating an Account and Writing a Letter

The app lets you register, log in, and write letters. Think of it as a private messaging or diary feature.

Website prompting the user to login or create an account
What the app looks like

I created a test account and wrote a letter just to see how the app behaves.

After submitting, I got redirected to /letters

Endpoint showing the list of the letter I have written
/letters endpoint

my newly created letter was sitting at /letter/3 :

my letter displayed on the endpoint
letter endpoint

That number jumped out immediately. Sequential integer IDs in URLs are one of the classic signs of a potential IDOR vulnerability. There's also a "Tip from Cupid" hint in the UI that nudges you in exactly this direction.

What Is IDOR?

IDOR stands for Insecure Direct Object Reference. It happens when an application uses a user-controllable value like an ID in a URL, to directly access an object (a database record, a file, a letter) without checking whether the requesting user is actually allowed to see it.

In plain terms: the server assumes that if you know the ID, you're allowed to see it. That assumption is wrong.

The "Exploit"

I changed the URL from /letter/3 to /letter/2.

It loaded. Someone else's letter, no error, no redirect, no warning.

endpoint displaying someone else’s letter through IDOR
Someone else's letter

Then I tried /letter/1.

Endpoint displaying the first letter through IDOR, with the flag within
Flag

That's it. No payload, no script, no tools. Just a different number in the address bar. The server never once checked whether I was the owner of those letters, it just handed them over.

Why This Is Serious

In a CTF, IDOR gets you a flag. In a real application, it gets an attacker access to every private message, every personal document, every piece of sensitive data in the system just by counting upward from their own ID.

This vulnerability has shown up in major real-world platforms. It consistently ranks in the OWASP Top 10 under "Broken Access Control" for a reason: it's easy to introduce, easy to overlook during development, and trivially easy to exploit.

How Could This Have Been Prevented?

The fix is straightforward in concept, even if it requires discipline to implement consistently: every time a user requests an object, the server must verify they own it or have permission to access it.

It's not enough to just make IDs harder to guess by switching from sequential integers to random UUIDs, though that does raise the bar. The real fix is a server-side ownership check every single time, something like: "does the user making this request own the letter they're asking for?" If not, return a 403 and stop there.

This check needs to happen on the server. Hiding buttons in the UI or relying on the user "not knowing" the ID of someone else's letter is not access control, it's just hoping nobody looks too closely.

What I Took Away

This was the quickest flag of the CTF so far. The lesson isn't just "check for IDOR", it's that access control needs to be a deliberate, server-side decision for every single endpoint, not an afterthought. The moment you see a sequential ID in a URL, that question should be automatic: does the server actually verify I'm allowed to see this?

Thanks for reading. More writeups from this CTF coming soon.