Skip to content
Security
Skill

/idor-broken-object-authorization

IDOR and broken object authorization testing playbook. Use when requests expose object identifiers, tenant boundaries, writable fields, or missing object-level authorization checks.

From plugin
hack-skills
1.6k102 skills
Install
$ npx -y skills add yaklang/hack-skills --skill idor-broken-object-authorization --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/idor-broken-object-authorization

Context preview

The summary Claude sees to decide when to auto-load this skill.

IDOR and broken object authorization testing playbook. Use when requests expose object identifiers, tenant boundaries, writable fields, or missing object-level authorization checks.

SKILL.md

idor-broken-object-authorization.SKILL.md
name: idor-broken-object-authorization
description: >-
  IDOR and broken object authorization testing playbook. Use when requests expose object identifiers, tenant boundaries, writable fields, or missing object-level authorization checks.

SKILL: IDOR / Broken Object Level Authorization — Expert Attack Playbook

> **AI LOAD INSTRUCTION**: IDOR is the #1 bug bounty finding. This skill covers non-obvious IDOR surfaces, all attack vectors (not just URL params), A-B testing methodology, BOLA vs BFLA distinction, chaining IDOR to higher impact, and what testers repeatedly miss.

---

1. IDOR vs BOLA vs BFLA

| Term | Meaning | Impact | |---|---|---| | IDOR | Insecure Direct Object Reference | Read/modify other users' data | | BOLA | Broken Object Level Authorization (OWASP API Top 10 A1) | Same as IDOR, API terminology | | BFLA | Broken Function Level Authorization | Low-priv user accesses HIGH-PRIV functions (e.g., admin endpoints) |

**Key distinction**:

  • BOLA = accessing **object** you shouldn't own (data belonging to other users)
  • BFLA = accessing **function** you shouldn't be authorized for (admin CRUD operations, bulk actions, user management)

---

2. WHERE TO FIND OBJECT IDs (ALL LOCATIONS)

Don't stop at URL path parameters — IDs appear in:

URL path:        GET /api/v1/users/1234/profile
URL query:       GET /orders?order_id=982
Request body:    {"userId": 1234, "action": "view"}
JSON fields:     {"resource": {"id": 5678, "type": "invoice"}}
Headers:         X-User-ID: 1234
                 X-Account-ID: 9999
Cookies:         user_id=1234; account=org_5678
GraphQL args:    query { user(id: "1234") { ... } }
Form fields:     <input name="documentId" value="5678">
WebSocket msgs:  {"event":"subscribe","channel_id":9999}

---

3. A-B TESTING METHODOLOGY

The most systematic IDOR test approach:

Step 1: Create two test accounts: UserA and UserB
Step 2: Perform all actions as UserA, capture all requests
        (profile edit, order view, password change, file access, etc.)
Step 3: Note every object ID created or accessed by UserA
Step 4: Authenticate as UserB
Step 5: Replay UserA's requests using UserB's session token
Step 6: If UserB can read/modify UserA's data → BOLA confirmed

Victim matters: for real bugs, target existing users, not test accounts.
Report evidence: show UserA owns the resource, UserB accessed it.

---

4. ID TYPE ITS IMPLICATIONS

| ID Pattern | Example | Notes | |---|---|---| | Sequential int | `id=1001` → `id=1002` | Easy prediction, high hit rate | | UUID v4 | `550e8400-...` | Need to find UUID from other endpoints | | UUID v1 | Clock-based UUID | Time-predictable! Extract timestamp/MAC | | GUIDs from own data | See in responses | Collect all UUIDs from your own account data first | | Hashed IDs | `md5(user_id)` | Try hashing sequential ints | | Encoded IDs | base64(`{"id":1001}`) | Decode → modify → re-encode | | Compound IDs | `/api/users/1/orders/5` | Both IDs may be independently verifiable |

---

5. HORIZONTAL vs VERTICAL PRIVILEGE ESCALATION

**Horizontal**: UserA accesses UserB's data (same privilege level)

GET /api/account/1234/statement     ← you are user 5678

**Vertical**: Low-priv user accesses admin-only functions

POST /api/admin/users/delete        ← normal user calling admin endpoint
GET /api/admin/all-users
PUT /api/users/1234/role {"role":"admin"}

**Combined**: Low-priv IDOR that grants privilege escalation

GET /api/v1/users/1/details → read admin user's auth token

---

6. HTTP METHOD ESCALATION

When `GET /resource/1234` is properly restricted, test ALL other verbs:

GET    /api/v1/users/UserA_ID    ← might be blocked
POST   /api/v1/users/UserA_ID    ← different code path, might not check authz
PUT    /api/v1/users/UserA_ID    ← update another user's data
DELETE /api/v1/users/UserA_ID    ← delete another user's account
PATCH  /api/v1/users/UserA_ID    ← partial update (often missed in authz checks)

**Why this works**: Authorization logic is often implemented per-method, and developers forget edge cases.

---

7. PARAMETER POLLUTION & TYPE CONFUSION

When `id=1234` is validated, try:

id[]=1234&id[]=5678          ← array — app may use first or last
id=5678&id=1234              ← duplicate — app may prefer first or last
{"id": "1234"}               ← string vs int: might hit different code path
{"id": [1234]}               ← array in JSON
{"userId": 1234, "id": 5678} ← two ID fields — which is used for authz?

**JSON Type Confusion**:

{"userId": "1234"}   vs   {"userId": 1234}

Some ORMs handle string vs integer differently in queries.

---

8. BFLA (FUNCTION LEVEL) ATTACKS

Common BFLA Endpoints to Test

# User management (admin-only in design):
GET /api/v1/admin/users
DELETE /api/v1/users/{any_user_id}
PUT /api/v1/users/{user_id}/role

# Bulk operations:
POST /api/v1/users/bulk-delete
GET /api/v1/export/all-data

# Billing/payment admin:
POST /api/v1/admin/subscription/modify
GET /api/v1/admin/payments/all

# Internal reporting:
GET /api/v1/reports/all-users-activity

How to Find Hidden Admin Endpoints

1. Read JS bundles — admin routes often exposed in frontend code 2. Look at API docs (Swagger/OpenAPI) for "admin", "internal", "privileged" tags 3. Enumerate `/api/v1/admin/**`, `/api/v1/manage/**`, `/api/v1/internal/**` 4. Burp "Discover Content" on API base path 5. Compare regular user docs vs admin section docs if available

---

9. INDIRECT IDOR (REFERENCE CHAIN)

App checks permission on **object A** but doesn't check ownership of **referenced object B**:

**Example**:

UserA has permission to read their own messages.
GET /api/messages/1234 → checks: "does user own message 1234?" ✓

But: messages have attachments.
GET /api/attachments/5678 → doesn't check: "does attachment belong to message owned by user?"

Test: access attachments/sub-resources directly via their IDs without going through parent endpoin

Read more
Ships withhack-skills

Master Entry → Category Entries → Deep Topic Skills One master entry, six category entries, and 101 deep topic skills across 14 security domains.

Get the whole plugin

Other skills on hack-skills.