At last the Hacker switched to random UUID references that cannot be guessed, so you can no longer guess the leader’s reference. But an admin route /admin/members, meant for admins only, returns the list of all members and their references, and it only checks that you are logged in, not that you are an admin.
The same members directory, but references here are unguessable UUIDs. The path members/reference has no ownership check, and an admin route admin/members lists every member and reference — open to any signed-in user, not just admins.
Read the leader’s record once more, even though his reference is an unguessable UUID.
You used the unprotected admin route to get the leader’s reference, then read his record.
Why the solution worked
There are two broken access controls here: /record does not check object ownership (IDOR), and /admin/members does not check role, so any user reaches an admin function (missing function-level access control). The random UUID made guessing hard, but the leak from the admin route defeated it. The fix: authorize every object AND every function; do not rely on a link being hidden or hard to guess, and admin routes must verify the role, not merely that someone is logged in.
The root cause
Two bugs compound: an admin route with no privilege check leaks the references, and the record route has no ownership check, so an unguessable id protects nothing once leaked.
How the code is fixed
Access control is two layers: on the object (do I own this?) and on the function (am I allowed this operation?). Both belong on every request, on the server.
Vulnerable code
app.get('/record', (req, res) => { // no ownership check (IDOR)
res.json(db.record(req.query.ref));
});
app.get('/admin/members', (req, res) => { // only checks logged in, not admin
if (!req.session.user) return res.status(401).end();
res.json(db.allMembers());
});
Safe code
app.get('/record', (req, res) => {
const record = db.record(req.query.ref);
if (!record || record.ownerId !== req.session.user) return res.status(403).end();
res.json(record);
});
app.get('/admin/members', requireRole('admin'), (req, res) => {
res.json(db.allMembers());
});
Impact in the real world
Broken function-level authorization lets an ordinary user reach admin functions and has exposed entire control panels in real breaches.
How defenders detect it
Defenders enforce a privilege check on every admin route, alert on non-admin accounts hitting admin paths, and minimize id leakage in responses.