
What a Single File Name Taught Me About IDOR (PortSwigger Lab)
My transcript downloaded as 2.txt. That was the entire vulnerability, sitting right there in a file name, and it took less time to exploit than it did to notice.
This is a PortSwigger Web Security Academy lab, part of the access control section I’ve been working through. The setup is a support chat feature that stores each user’s transcript directly on the server’s file system and serves it back through a static URL when you click “View Transcript.” There’s no session-based DB lookup or verification. A file is just handed over on request.
The goal was to find the password for a user called carlos, hidden somewhere in his transcript, and log in as him.
Noticing the pattern
I opened my own transcript first, just to see what a normal request looked like. The file that downloaded was named 2.txt. That’s the moment the lab clicks. If mine is 2.txt, something somewhere is 1.txt, and the server has no reason to think I shouldn’t be able to ask for it directly.
I checked the request in Burp Suite and looked at the page’s JS in Firefox, mostly to confirm I understood how the download was actually being triggered rather than just assuming. Then I requested 1.txt from the same path instead of 2.txt.
CONNECTED: -- Now chatting with Hal Pline --
You: Hi Hal, I think I've forgotten my password and need confirmation that I've got the right one
Hal Pline: Sure, no problem, you seem like a nice guy. Just tell me your password and I'll confirm whether it's correct or not.
You: Wow you're so nice, thanks. I've heard from other people that you can be a right ****
Hal Pline: Takes one to know one
You: Ok so my password is 42i8tjjc5mz0w2vvedoq. Is that right?
Hal Pline: Yes it is!
You: Ok thanks, bye!
Hal Pline: Do one!
The server handed it over. No ownership check, no “does this session belong to the user whose file this is.” Carlos’s password was sitting in the transcript. I logged in as him. Lab solved, and honestly, it felt almost too easy for how the concept is usually talked about.
Why this counts as IDOR and not just “broken access control”
Going into this lab I genuinely didn’t think IDOR deserved its own category. It still looks like any other horizontal access control failure to me: a user accessing something that belongs to someone else. What makes it IDOR specifically is narrower than that. The system is deliberately retrieving a resource based on a value the user controls, in this case a file name, and never validating that value against who’s actually asking. The vulnerability isn’t “access control is missing” in the abstract. It’s that a direct reference to a specific object got exposed to the client, and the server trusted it at face value.
The fix
Two ways to close this, and they’re not mutually exclusive:
- Stop letting the client name the resource at all. Map the authenticated session to its own file server-side, so the request never needs to carry a raw identifier the user could tamper with in the first place.
- If an identifier has to be exposed to the client, make it something you can’t guess your way through, a UUID instead of a sequential integer, and still check ownership server-side regardless. An unguessable name raises the cost of the attack. It doesn’t replace the authorization check. Sequential IDs just make the “regardless” part obvious faster.
What I learned
The fix here is the same instinct every access control lab in this section has been teaching me: check ownership server-side, every time, no exceptions for “well, the identifier is hard to guess.” IDOR is what happens when that instinct gets skipped specifically at the point where a request maps to a stored resource. Everything else about it is just horizontal access control wearing a more specific name.
Cover photo by Maksym Kaharlytskyi on Unsplash