Broken Access Control Testing for Defenders
Broken access control testing for defenders — detect IDOR and BOLA from authorization-failure telemetry with Sigma and SPL rules, plus deny-by-default hardening.
Broken access control testing, for a defender, is a two-part job: verify that every endpoint enforces ownership server-side, and instrument authorization failures so abuse is visible in real time. The fingerprint of an IDOR or BOLA attack is unmistakable in logs: one account walking sequential object IDs, or a burst of 403s as an attacker maps which references it can reach. This guide ships the test logic and the detection.
Broken access control is the #1 risk in the OWASP Top 10 (A01), held across consecutive editions and found in the large majority of applications tested. It is the most common serious web flaw, and the hardest to fix with a single patch.
What is broken access control?
Broken access control is the failure of the rule that user A cannot read user B’s data. When it breaks, an attacker who is fully, legitimately logged in changes an ID in a request and reads someone else’s invoice, message, or medical record. No exploit, no malware — just a logged-in user asking for a resource the server hands over without checking ownership.
This maps to MITRE ATT&CK T1190 — Exploit Public-Facing Application, and the resulting access looks like T1078 — Valid Accounts because the attacker is a valid account. That overlap is why detection has to focus on behavior, not credentials.
What is the difference between IDOR and BOLA?
IDOR and BOLA are the same flaw under two names — the server trusts a client-supplied ID without verifying the requester owns that object. IDOR (Insecure Direct Object Reference) is the classic web term; BOLA (Broken Object Level Authorization) is the OWASP API Security Top 10 API1:2023 equivalent. The variants differ only in direction and goal:
| Variant | What the attacker does | Telemetry fingerprint | Detection |
|---|---|---|---|
| Horizontal (IDOR/BOLA) | Swaps an object ID for another user’s | One session, many distinct object IDs in sequence | Enumeration rule |
| Vertical | Reaches functions above their role | 403s on admin paths, then a 200 that slips through | Privileged-path denials |
| Forced browsing | Probes for hidden references/endpoints | Rising 403/404 across many paths from one actor | Denial-spike rule |
A critical defender’s note: non-sequential IDs do not fix this. UUIDs raise the guessing cost, but an attacker who obtains a valid identifier (from a referrer, a shared link, or an API response) exploits the missing check just the same. Obfuscation is not authorization.
How to detect broken access control from telemetry
Authorization decisions are events, and abuse has a shape. Log every decision with actor, object, action, and allow/deny outcome — the same auth-event stream behind JWT misconfiguration detection — then two patterns surface the attack.
Detect object-ID enumeration
A single session touching many distinct object IDs on the same endpoint in a short window is the IDOR/BOLA signature. Normal users view their own handful of records, not hundreds in sequence.
title: Sequential Object-ID Access by Single Actor
id: 8b4e2d10-darkpwn-illustrative
status: experimental
logsource:
product: application
service: api
detection:
selection:
endpoint|contains: '/api/'
http_method: 'GET'
timeframe: 5m
condition: selection | count(distinct object_id) by actor_id > 50
falsepositives:
- Batch/reporting jobs and admin tooling that legitimately read many records
level: medium Detect authorization-failure spikes
A burst of denied requests across many resources is forced browsing. Counting deny outcomes per actor turns your authorization layer into an IDS.
index=app sourcetype=authz:decision outcome=deny
| bin _time span=5m
| stats count AS denies, dc(object_id) AS distinct_objects by _time, actor_id, src_ip
| where denies >= 20 AND distinct_objects >= 10 How to test for broken access control
Access-control bugs hide from automated scanners because the tools cannot infer business intent. Test it deliberately, in an environment you own:
- Create two accounts, A and B, each owning distinct objects.
- Authenticated as A, request B’s object IDs across every object-scoped endpoint. Every one should return 403/404, never B’s data.
- As a standard-role user, request admin endpoints. Every one should deny.
- Automate these as CI tests — one per role, per endpoint — so a new endpoint without an ownership check fails the build.
This pairs with confirming your detections fire, the way SQL injection detection gets validated against real telemetry.
How to defend against broken access control
Detection finds the gap. These design controls close it.
- Combine RBAC with explicit ownership checks. RBAC handles vertical access (who can do what); per-object ownership handles horizontal access (whose data). You need both.
- Centralize the authorization logic and reuse it, so one endpoint cannot quietly miss the check — and so the decision is loggable in a uniform format.
- Build access-control tests into CI, mapped to OWASP ASVS V4 Access Control.
Common access-control mistakes
- Front-end-only enforcement. Hiding a button does not stop a crafted request.
- Object obfuscation mistaken for authorization. UUIDs are not a control.
- Silent 403s. No event means no detection.
- Untested new endpoints. Every shipped route is a fresh chance to forget the check.
Broken access control checklist
A copy-paste list for code review and detection:
- Deny by default — every resource forbidden unless a rule grants access.
- Enforce ownership server-side: scope queries to the principal (
WHERE owner_id = :current_user). - Combine RBAC (vertical access) with per-object ownership checks (horizontal access).
- Centralize the authorization logic and reuse it across every endpoint.
- Emit a structured event for every allow/deny decision (actor, object, action, outcome).
- Alert on one actor accessing many distinct object IDs in a short window (enumeration).
- Alert on denial spikes across many resources from one actor (forced browsing).
- Add CI tests per role per endpoint: A cannot read B’s objects; a user cannot reach admin functions.
- Cover
PUT/PATCHenumeration and GraphQL field-level authorization, not justGETentry points.
The takeaway
Access control cannot be patched in one place, so you defend it in two: deny by default with server-side ownership checks, and instrument every authorization decision so enumeration and forced browsing show up as the anomalies they are. Continue across the web-application attack surface with SSRF detection and XSS CSP hardening, or explore the full Defensive Research pillar.
Training & tools referenced
Disclosure: Some links below are affiliate links. If you buy through them, darkpwn may earn a commission at no extra cost to you. We only recommend training and tools we actually use in our own lab, and affiliate links never influence editorial coverage.
- TryHackMeAuthorized labs to practice access-control testing and detectionSecurity TrainingStart training
Frequently asked questions
What is the difference between IDOR and BOLA?
They are the same flaw under two names. IDOR (Insecure Direct Object Reference) is the classic web term; BOLA (Broken Object Level Authorization) is the OWASP API Security Top 10 equivalent. Both mean the server trusts a client-supplied ID without verifying the requester owns that object.
Do UUIDs prevent IDOR?
No. UUIDs raise the cost of guessing an identifier, but an attacker who obtains a valid one — from a referrer header, a shared link, or an API response — still exploits the missing ownership check. Obfuscation is not authorization.
How do you detect broken access control?
Log every authorization decision with actor, object, action, and outcome, then alert on two patterns: a single actor accessing many distinct object IDs in a short window (enumeration), and a spike of denied requests across many resources (forced browsing).
What is the top OWASP risk?
Broken access control is A01 in the OWASP Top 10, the highest-ranked web application risk across consecutive editions, found in the large majority of applications tested.