Skip to main content
Back to Writeups
Web Security
6 min read

Broken Access Control: Patterns I Keep Seeing

Why Access Control Keeps Breaking

Access control sits at the intersection of business logic and security enforcement, which makes it one of the hardest things to get right consistently. Unlike injection flaws or misconfigurations, access control bugs often look like working features — they just work for people who shouldn't have access.

Pattern 1: Insecure Direct Object References

The classic. An endpoint like /api/invoices/1042 returns invoice data based solely on the ID in the URL. Change the number, get someone else's invoice. The fix is straightforward — validate that the authenticated user owns the requested resource — but it requires discipline at every endpoint.

Pattern 2: Missing Function-Level Access Control

Admin panels that check permissions in the UI but not on the server. The dashboard hides the "Delete User" button for non-admins, but the API endpoint /api/admin/delete-user happily processes requests from any authenticated session. Frontend controls are UX, not security.

Pattern 3: Privilege Escalation via Parameter Manipulation

Registration or profile update forms that include a role parameter. Intercepting the request and changing role=user to role=admin is trivial with a proxy. The server should never trust client-supplied role or permission values.

Pattern 4: Horizontal Privilege Escalation in Multi-Tenant Apps

Tenant isolation failures where User A in Organization 1 can access Organization 2's data by manipulating tenant identifiers in API calls. This is especially common in B2B SaaS platforms where tenant scoping wasn't part of the original architecture.

Closing Thoughts

Access control testing requires thinking like a user who wants to do things they shouldn't. Automated scanners miss most of these issues because they don't understand business context. Manual testing with a clear threat model is still the most reliable approach.