Sitemap

The IDOR That Played Hide-and-Seek in the URL Path

4 min readMay 27, 2025
Press enter or click to view image in full size

Finding vulnerabilities is often like detective work. You follow clues, look for inconsistencies, and sometimes, the culprit is hiding right where you least expect it. Today, I want to share a (hypothetical) story about an Insecure Direct Object Reference (IDOR) I found in a way different from the usual “change ID=123 to 124” in query parameters. This one was embedded in the URL path — affecting resource creation inside another user’s project.

A Quick IDOR Recap

An IDOR is an access control flaw that occurs when an application uses an identifier (like a user ID, file ID, or project ID) to access resources, but does not properly verify if the logged-in user has permission to access or modify that specific resource.

Imagine a numeric keypad that lets you open any hotel room just by entering the room number, without the system checking if your keycard actually matches that room. That’s what an IDOR feels like in web security.

The Target: SyncVault — A Collaborative Cloud Storage Platform

Our fictional target is SyncVault, a platform designed for teams and individuals to store, share, and collaborate on files and projects. Users have private storage spaces, can create projects, and invite others to collaborate.

The Setup: Uploading Files to Project Folders

Suppose I’m logged in as User_Alice. I create a project named Q4_Reports, which internally gets the ID proj-alice-q4r. When I upload a file to this project, the flow looks normal.

The URL for uploading files looks like this:

POST https://api.syncvault.example/v1/upload_to_project/{project_id}/new_file

With the project ID in the URL path — for example:

POST /v1/upload_to_project/proj-alice-q4r/new_file

The Clue: An Interesting URL Structure

Intercepting the request, I saw:

POST /v1/upload_to_project/proj-alice-q4r/new_file HTTP/1.1
Host: api.syncvault.example
Authorization: Bearer <Alice_Session_Token>
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW

------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="file_to_upload"; filename="annual_review.pdf"
Content-Type: application/pdf

(Binary data of annual_review.pdf)
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="target_folder_name"

"Confidential"
------WebKitFormBoundary7MA4YWxkTrZu0gW--------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="file_to_upload"; filename="annual_review.pdf"
Content-Type: application/pdf

The project_id was right there in the URL path. This is standard, but the backend must verify if Alice is authorized for that project before accepting the upload.

The Hypothesis: Can I Upload Files to Someone Else’s Project?

What if the server only checks that I’m an authenticated SyncVault user but does not check if I’m actually a member of the project specified by project_id in the URL path?

If true, I could upload files into any project by guessing or knowing its ID.

The Test: Crafting a Malicious Request

Let’s say I discovered a project ID belonging to User_Bob: proj-bob-tsd.

Press enter or click to view image in full size

Using my proxy tool (like Burp Suite), I took the original upload request and changed only the project ID:

POST /v1/upload_to_project/proj-bob-tsd/new_file HTTP/1.1
Host: api.syncvault.example
Authorization: Bearer <Alice_Session_Token> // Still Alice’s token
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW

------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="file_to_upload"; filename="malicious_payload.exe"
Content-Type: application/octet-stream

(Binary data of malicious_payload.exe)
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="target_folder_name"

"DO_NOT_OPEN"
------WebKitFormBoundary7MA4YWxkTrZu0gW--
Press enter or click to view image in full size

I sent this request…

The Result: Alice’s File in Bob’s Fort Knox

The server responded with 201 Created! No errors, no access denied.

When Bob logs in, he finds a new suspicious file named malicious_payload.exe in the "DO_NOT_OPEN" folder of his project — uploaded by Alice, without his permission.

This is a clear IDOR vulnerability!

Why This IDOR Slipped Through

  • Focus on Body/Query Parameters Only: Many devs and testers expect IDs in query strings or JSON bodies, missing path parameters.
  • Poor Separation of Authorization Logic: Authentication checked Alice is a valid user, but project authorization was skipped or assumed based on session context.
  • Assumed Previous Selection: The system may have assumed once a project is selected, all subsequent requests belong to that project — ignoring explicit project IDs in API paths.

Impact of This IDOR

  • Data Injection & Corruption: Upload malicious files, overwrite existing files.
  • Denial of Service: Fill someone else’s storage quota.
  • Malware Distribution: If files get previewed or executed.
  • Reputation Damage: Users lose trust in the platform.
  • Further Attacks: Upload backdoors, phishing pages, or malicious scripts.

Mitigation: How Developers Should Fix This

  • Enforce Explicit Authorization: Always verify that the authenticated user has permission to access or modify the resource referenced by the ID in any part of the request — path, query, or body.
  • Centralize Access Control: Use a dedicated access control module to avoid scattered and inconsistent checks.
  • Use Non-Guessable IDs: UUIDs or random tokens make guessing IDs harder (but don’t rely solely on this).
  • Thoroughly Test All Parameters: Include path parameters in security tests and code reviews.
  • Never Trust Client Input: Treat all IDs coming from the client as untrusted and validate permissions rigorously.

Conclusion

This (hypothetical) example from SyncVault reminds us that IDOR vulnerabilities can hide in unexpected places — even in URL paths during resource creation. Security testing should cover every input vector, and developers must never trust client-provided IDs without strict authorization checks.

Press enter or click to view image in full size

Stay curious, keep hunting, and remember: Authorisation is never optional!

Best regards,
Shubham Tiwari (Rooter)

Connect with Shubham via:
- Email: info
@shubhamrooter.com
- LinkedIn:
https://www.linkedin.com/in/shubham-tiwari09
- Twitter:
https://twitter.com/shubhamtiwari_r

Happy bug hunting! 🐞✨

--

--

No responses yet