Set up Listener

Hey folks!

If you’re just dipping your toes into web security or bug bounties, IDOR is one of those bugs you definitely wanna keep an eye out for. It’s simple, it’s sneaky, and best of all it pops up everywhere. Let’s break it down like we’re chilling in a dorm room, whiteboarding bug bounty tactics over some cold coffee.


What is IDOR?

IDOR stands for Insecure Direct Object Reference.

In plain English, it’s when a web app exposes a way for users to access data they shouldn’t just by tweaking something like a URL parameter, form data, or an API request.

Basically: the app “trusts” the user a little too much.

Now, what about Encoded IDs?

People often try to “hide” or “protect” those IDs by encoding them. Common ways:

  • Base64 encoding (very common, super easy to decode)

  • Custom hashing or encryption

  • Obfuscation schemes like Hashids

But guess what? Just encoding an ID is NOT the same as properly securing access. If the app doesn’t verify authorization, IDOR still happens, no matter how “fancy” the ID looks.

Example: Vulnerable EncodedID App

When we log in, our profile ID is 30.

On the profile page, we see basic info like:

  • Username

  • Email

If you check the URL, it looks something like this: /profile/<encoded_id>

That <encoded_id> is actually a Base64-encoded JSON string. For example:

eyJpZCI6IDMwfQ==

No Detection

If we decode it from Base64, it reveals:

{"id": 30}

Now here’s the catch admin usually has an ID of 1:

{"id": 1}

If we encode that, it becomes:

eyJpZCI6IDF9

No Detection

By swapping out the encoded ID in the URL with this admin one, we can gain access to the admin’s profile and email.


Why is this bad?

Because the app blindly trusts the client-provided encoded ID, anyone can tamper with it and impersonate other users no authentication needed. Classic insecure access control.

What’s the deal with Hashed IDs and IDOR?

Apps try to level up their game by hashing IDs instead of sending raw, sequential IDs in URLs or API requests. The idea? Make it harder for attackers to guess or manipulate those IDs and access unauthorized data.

But here’s the catch hashing alone ain’t security. If the backend doesn’t check user permissions or if the hashing method is weak or reversible, IDOR still slaps hard.

Why hashed IDs can still be broken and abused:

  1. Deterministic Hashing: Most hashes (MD5, SHA1, SHA256) are deterministic. Same input = same output. If you know or guess the input space (like user IDs from 1 to 10,000), you can generate a full rainbow table or brute force hashes offline.

  2. No Salting or Secret Keys: If the hash is just hash(ID) with no salt or secret, it’s an open invitation for brute force. Attackers can precompute hashes and reverse map.

  3. Lack of Backend Authorization: Even if the hash is strong, if the server just decodes the hash and fetches the object without verifying who owns it or if the requester has rights, boom IDOR.

  4. Weak Hash Algorithms: MD5 and SHA1 are outdated and cracked. Using these for hashing IDs is like locking your door with a plastic key.

Breaking Down an IDOR Vulnerability Using MD5 Hashes

In this scenario, we’ve got an IDOR (Insecure Direct Object Reference) vulnerability that’s relying on an MD5 hash as an identifier.

Here’s the URL pattern we’re looking at:

/profile/202cb962ac59075b964b07152d234b70

No Detection

This is an MD5 hash. If we crack it using something like CrackStation, it reveals the original value:

123

No Detection

Now, if we generate the MD5 hash for the value 1, we get:

c4ca4238a0b923820dcc509a6f75849b

No Detection

If we substitute that hash into the URL:

/profile/c4ca4238a0b923820dcc509a6f75849b

No Detection

we gain access to an admin profile!

Cracking IDOR with Unpredictable IDs A Tale of Two Accounts

So picture this: I’m chilling in my dorm, knocking out some bug bounty recon between classes and ramen breaks. I’m poking around this web app nothing too crazy when I notice that the resource URLs use these wild, unpredictable ID strings. I’m talking UUIDs like 95a1c0f4-d3ff-11ed-afa1-0242ac120002 instead of classic ?id=123.

At first glance? Looked locked down. Couldn’t enumerate. Brute-forcing? Dead on arrival.

But here’s where it gets spicy.


Create Two Accounts

Let’s say we’re testing a web app where each user has a unique UUID assigned to their profile or data page. We set up two accounts:

  • StudentA our real account

  • StudentB a test dummy

When we visit each profile’s “view” page, the URL looks like this:

No Detection

StudentA:

/view/f2ffe812-4c39-4fb8-bda9-fca481a077d4

StudentB:

/view/2013bc6e-93b7-43a7-8ca3-27e18fedae7f

No Detection

Now here’s the test:

While logged in as StudentA, we manually change the URL to:

/view/2013bc6e-93b7-43a7-8ca3-27e18fedae7f

we can now access StudentB’s content, even though it’s a different account.

No Detection

No Detection


Why This Is Bad

This is a classic IDOR (Insecure Direct Object Reference) vuln. Even though the IDs are UUIDs (long, random, hard to guess), the backend doesn’t check if StudentA actually owns or has permission to view that UUID.

The server sees a valid ID, retrieves the data, and serves it no access control check.