Broken Access Control is the most dangerous web vulnerability in 2023 according to OWASP — ranking #1 in the OWASP Top 10. It happens when an application fails to enforce who is allowed to access which data. The most common form is Insecure Direct Object Reference (IDOR): a user changes a number in a URL or API request and retrieves another user's records because the server never checks ownership. For Indian developers and security teams, this vulnerability is responsible for a disproportionate share of data breaches affecting customer records, financial data, and regulated personal information.
What Is Broken Access Control
Access control is the mechanism that enforces "user A can only read and modify user A's own data." When that enforcement is absent, incomplete, or bypassable, the application has broken access control.
OWASP lists it at A01:2021 — the top position — because it was found in 94 percent of tested applications during their research cycle. The category consolidates several related weaknesses that were previously separate in older OWASP editions, including IDOR, path traversal, privilege escalation, and missing function-level access control.
Authentication vs Authorisation: The Core Gap
Most Indian development teams implement authentication correctly — a login form, OTP, JWT token. The failure happens at the next step: authorisation. These two concepts are distinct:
| Concept | Question it answers | Common implementation |
|---|---|---|
| Authentication (AuthN) | Who are you? | OTP, password, OAuth token |
| Authorisation (AuthZ) | Are you allowed to do this? | Ownership check, RBAC, ABAC |
| IDOR failure | AuthN passed, AuthZ never ran | Server uses ID from request, skips ownership check |
What IDOR Looks Like
IDOR (Insecure Direct Object Reference) occurs when a user-controlled value — an ID, filename, or reference — is used directly to fetch a backend object without verifying that the requesting user owns or has rights to that object.
Vulnerable example (Node.js / Express):
// VULNERABLE — no ownership check
app.get('/api/orders/:id', authenticateJWT, async (req, res) => {
const order = await db.orders.findById(req.params.id);
return res.json(order);
});Here authenticateJWT confirms the user is logged in — authentication passes. But the query returns any order matching req.params.id, regardless of whether order.userId === req.user.id. A logged-in attacker can iterate id values and exfiltrate every order in the database.
Fixed example:
// SECURE — ownership enforced at query level
app.get('/api/orders/:id', authenticateJWT, async (req, res) => {
const order = await db.orders.findOne({
where: { id: req.params.id, userId: req.user.id } // authz: ownership
});
if (!order) return res.status(404).json({ error: 'Not found' });
return res.json(order);
});The fix binds userId to the authenticated user's identity inside the query. The attacker's request now returns 404 regardless of which ID they supply.
Know your vulnerabilities before attackers do
Run a free VAPT scan — takes 5 minutes, no signup required.
Book Your Free ScanHow an IDOR Attack Flows
The diagram below shows the complete attack path and where the authorisation gate must be inserted.
graph TD
A[Attacker logs in
authenticated as User B]:::normal --> B[Sends GET /api/invoice/1001
User B owns invoice 2055]:::danger
B --> C{Server receives request}:::normal
C --> D[JWT verified — AuthN passes]:::success
D --> E{Ownership check present?}:::normal
E -->|No check| F[Query DB by id=1001
no user filter]:::danger
F --> G[Returns User A invoice
IDOR exploited]:::danger
E -->|Check present| H[Query DB where id=1001
AND userId=B]:::success
H --> I{Record belongs to B?}:::success
I -->|Yes| J[Return invoice to B]:::success
I -->|No| K[Return 404 Not Found
attack blocked]:::success
classDef normal fill:#1e3a5f,stroke:#3B82F6,color:#e2e8f0
classDef danger fill:#5f1e1e,stroke:#EF4444,color:#e2e8f0
classDef success fill:#1e3d2f,stroke:#10B981,color:#e2e8f0BOLA: The API-era Name for IDOR
BOLA (Broken Object Level Authorisation) is the OWASP API Security Top 10 equivalent of IDOR, specifically framed for REST and GraphQL APIs. If your product exposes an API — a mobile app backend, a B2B integration endpoint, a SaaS webhook — BOLA is the primary risk to assess.
The mechanics are identical: an authenticated API caller supplies an object identifier they do not own and receives data they should not see. The difference is context: web IDOR often involves a browser URL or form field; BOLA involves API request bodies, path parameters, and query strings.
OWASP's API Security project lists BOLA at API1:2023 — the single highest-risk API vulnerability.
Horizontal vs Vertical Privilege Escalation
Broken access control manifests as two distinct escalation patterns:
Horizontal escalation — A user accesses resources belonging to another user at the same privilege level. Example: logged-in customer views another customer's invoice by changing the ID. This is the classic IDOR scenario.
Vertical escalation — A lower-privileged user accesses functions or data reserved for a higher privilege level. Example: a standard user calls /api/admin/users and gets a full user list because the route only checks authentication, not the admin role.
Both are covered under OWASP A01. Both require the same fix: enforce authorisation server-side for every object and every function, not just at the route entry point.
pie title Web Apps Tested by OWASP 2021 — A01 Broken Access Control Presence
"Broken Access Control Found" : 94
"No Finding" : 6Real-World IDOR Patterns Found in Indian Applications
These are categories of IDOR commonly found during automated VAPT assessments — not fabricated scenarios, but structural patterns that recur across industries:
1. Sequential integer IDs in financial APIs
Invoice, order, and payment endpoints using auto-increment primary keys (/api/payment/1, /api/payment/2) without ownership binding. An attacker with one valid ID can enumerate the entire payments table.
2. UUID does not replace authorisation Switching from integer IDs to UUIDs reduces guessability but does not prevent IDOR. A UUID that leaks through a shared link, log entry, or another endpoint becomes exploitable.
3. GSTIN and PAN lookups without tenant scoping Tax and compliance portals that return entity data based on a GSTIN or PAN parameter without verifying the requesting user's relationship to that entity.
4. Document download endpoints
/api/documents/download?file=contract_1234.pdf returns any document if the filename is guessed or enumerated, bypassing all upload-time access controls.
Prevention: Enforce Authorisation Server-Side on Every Object
The NIST SP 800-53 access control family (AC controls) and OWASP's authorisation cheat sheet align on the same principles. Translate these into your codebase:
| Control | What it means | Implementation |
|---|---|---|
| Deny by default | If no explicit grant exists, deny | Every new route starts with return 403 until ownership logic is added |
| Enforce at object level | Check ownership on every fetch, not just route entry | Bind userId / tenantId in every DB query, not just in middleware |
| Indirect references | Never expose internal IDs to clients | Use UUIDs or map public tokens to internal IDs server-side |
| Centralise authz logic | One authorisation module, not scattered if checks | Use a policy engine or a dedicated canAccess(user, resource) function |
| Audit log access | Log every object access with the requester's identity | Feed into your SIEM or incident tracker |
| Automated testing | IDOR is testable — automate it in CI | Use VAPT tooling or DAST scanners in your pipeline |
Deny by Default in Practice
// Central ownership guard — reusable
async function requireOwnership(userId, resourceId, table) {
const record = await db[table].findOne({
where: { id: resourceId, userId }
});
if (!record) throw new ForbiddenError('Access denied');
return record;
}
// Every handler calls the guard — no scattered checks
app.get('/api/invoices/:id', authenticateJWT, async (req, res) => {
const invoice = await requireOwnership(req.user.id, req.params.id, 'invoices');
return res.json(invoice);
});This pattern makes IDOR structurally impossible on any endpoint that uses the guard — and makes auditing easy because authorisation lives in one place.
DPDP Act Compliance and Access Control
India's Digital Personal Data Protection Act 2023 (MeitY) imposes obligations on Data Fiduciaries to implement technical safeguards for personal data. An IDOR vulnerability that allows unauthenticated or cross-user access to personal data is a direct failure of this obligation.
The DPDP Act requires that personal data be processed only for consented purposes and be protected from unauthorised access. A customer exposing their own account data through an IDOR flaw can lead to a reportable breach under the Act — with penalties scaling with the severity of the failure.
If your organisation needs a structured compliance assessment, the DPDP compliance page covers the intersection of VAPT findings and DPDP obligations.
What CERT-In Recommends
CERT-In's vulnerability disclosure programme and its published guidelines for web application security consistently flag broken access control as a high-severity finding. Under CERT-In's incident reporting rules (Information Technology Amendment Rules 2022), organisations must report certain categories of data breaches within six hours. An IDOR-driven breach affecting customer financial or personal data qualifies.
Organisations seeking a CERT-In-aligned assessment should engage a CERT-In empanelled partner for formal reporting — the automated scan surfaces the technical vulnerabilities; empanelled-partner engagement for formal reporting is available as a separate service.