Hey everyone, I’m Moyin, a Web Penetration Tester. Today, I want to walk you through a recent engagement where a simple tip from a friend led me down a rabbit hole, eventually resulting in the discovery of two critical IDOR (Insecure Direct Object Reference) vulnerabilities.
These flaws led to the exposure of sensitive Personally Identifiable Information (PII) and private academic records on a school portal serving over 35,000 students at a research institution.
Before we dive into the technical details, let’s quickly establish the basics.
IDOR stands for Insecure Direct Object Reference. It’s an access control vulnerability that occurs when an application provides direct access to objects based on user-supplied input without properly checking permissions.
A Simple Example:
Imagine you are viewing your profile on a web app and the URL looks like this:
https://example.com/profile?id=123
If you change that ID number by just one digit:
https://example.com/profile?id=124
...and you suddenly have access to another user's private profile, you’ve just found an IDOR. The application trusted your request without verifying if you were authorized to view user 124's data.
For this hunt, I kept things simple and effective:
Every good hunt starts with curiosity. A course mate of mine, who is also a web developer, mentioned something unusual about the school portal. He noticed that the API endpoints were returning a massive amount of unnecessary data in their responses. While the frontend UI only displayed what was needed, the backend was essentially dumping everything it had.
I thought, "That’s weird... and a huge red flag." Naturally, I fired up Burp Suite and logged into the portal with my own student credentials to see what was happening under the hood.
To interact with the portal, you must be authenticated. I sent a standard POST request to /api/login with my username and password. While the response successfully returned the necessary session data (full name, DOB, etc.), it also returned a massive internal configuration dump nested as institution.culture and institution_culture.