Broken Object Level Authorization (BOLA/IDOR)

VerifiedCaution

Use when hunting Broken Object Level Authorization (BOLA) or Insecure Direct Object Reference (IDOR) vulnerabilities in APIs or web applications.

Sby Skills Guide Bot
SecurityIntermediate
7/22/2026
Claude Code
#bola#idor#authorization#api-security#owasp

Recommended for

Automated summary

This skill guides the hunt for Broken Object Level Authorization (BOLA/IDOR) vulnerabilities in APIs and web apps by replaying a victim account's requests with an attacker's token.

Strengths

  • A structured ten-step methodology covering identifier mapping, unauthenticated tests, write operations (PUT/PATCH/DELETE), and second-order IDOR
  • Ships concrete ready-to-run payloads: ffuf over numeric ID ranges, curl ID swapping, .json suffixes, deprecated API versions, and JSON globbing tricks
  • Grounded in recognized references (OWASP WSTG-ATHZ-04) and recommends the Burp Suite Autorize extension
  • Sharp list of trigger signals (user_id/owner_id params, "me" aliases, share links, export endpoints) that speeds up targeting

Limitations

  • The provided document is truncated mid-sentence in the Autorize extension description
  • Assumes two isolated test accounts and an explicit authorization scope, so it is unusable on a target without written permission
  • Does not address property-level authorization (BOPLA) or remediation/fix guidance
When to use it

Use it during an authorized penetration test of an API or web app where object identifiers (numeric or UUID) flow through URLs, request bodies, or cookies.

When not to use it

Avoid it on any system you lack written permission to test, or when the target API exposes no client-supplied object identifiers.

Security analysis

Caution
Quality score80/100

This is a conventional BOLA/IDOR testing methodology derived from OWASP WSTG-ATHZ-04. It declares no tools and contains no destructive, exfiltrating, or obfuscated actions; every command targets a user-supplied TARGET with user-supplied tokens. The only risk is inherent dual-use: it enables active probing and access-control bypass attempts against live APIs, which is legitimate only under authorized testing. Hence 'caution' rather than 'safe', and clearly not 'risky'.

Findings
  • •Includes commands (curl, ffuf, Burp Intruder/Autorize) that send live authenticated requests to target systems; safe only when the user has explicit authorization to test the target
  • •Payload guidance (ID fuzzing, HTTP verb swapping, JSON globbing, path traversal, second-order async abuse) is dual-use offensive technique, though scoped to authorized pentesting and contains no destructive or exfiltrating automation
  • •No credential, token, or secret handling; tokens are placeholders (YOUR_TOKEN) and no data is sent to third parties
  • •No obfuscated payloads, no curl|sh, no rm -rf, no safety-disabling instructions
How this analysis is made

Examples

Audit d'une API de commandes
I have written authorization to test https://api.example.com. I created two accounts, attacker_a and victim_b, and captured victim_b's requests in Burp. Help me test /api/orders/{id} and /api/users/{id}/profile for BOLA, including write operations and unauthenticated requests.
Fuzzing d'ID numériques
My own order ID is 1042 and I'm authenticated with a bearer token. Give me an ffuf command to fuzz IDs 1000-2000 on /api/receipts/FUZZ and explain how to filter false positives from the response sizes.
IDOR de second ordre et API obsolète
Walk me through testing second-order IDOR via a scheduled export job that references a victim's invoice ID in the request body, and check whether /v1/ endpoints still accept the swapped ID.

name: bola-idor description: > Use when hunting Broken Object Level Authorization (BOLA) or Insecure Direct Object Reference (IDOR) vulnerabilities in APIs or web applications. Trigger on: "BOLA", "IDOR", "broken object level", "access other users", "object reference", numeric or UUID IDs in URLs or request bodies, user-scoped resources, horizontal privilege escalation, "change the ID in the request", second-order IDOR, blind IDOR, indirect reference, encoded ID, deprecated API version, JSON globbing. license: MIT compatibility: Designed for Claude Code. Burp Suite (Autorize extension) or curl recommended. metadata: category: authorization version: "0.2" source: https://owasp.org/www-project-web-security-testing-guide/stable/ source_types: framework wstg: WSTG-ATHZ-04

Broken Object Level Authorization (BOLA / IDOR)

What Is Broken and Why

The server accepts a resource identifier from the client and fetches the object without verifying the requesting user owns or has access to it. Authorization is enforced at the route level ("is this user logged in?") but not at the object level ("does this user own object 1042?"). An attacker substitutes their identifier for a victim's to read, modify, or delete resources they should never access. BOLA is consistently the #1 OWASP API Security risk because it is trivial to test and almost always yields high-severity findings.

Key Signals

  • Numeric or sequential IDs in URL path: /api/orders/1042, /users/7/profile
  • UUIDs or hashes in query params or body referencing another user's object
  • Parameters named user_id, account_id, owner_id, ref, target_id, invoice
  • Write operations (PUT/PATCH/DELETE) accepting an object ID
  • Export/download/share endpoints with a resource ID parameter
  • Keywords me or current used as ID aliases — swappable for integer IDs
  • Older API versions still accessible: /v1/, /v2/, /legacy/
  • UUIDs discoverable via public profiles, share links, password reset flows, Wayback Machine

Methodology

  1. Map all object identifiers across the entire app — URLs, query params, request body, cookies, headers.
  2. Create two accounts with distinctive names (e.g. attacker_a, victim_b). Use separate browsers to keep sessions fully isolated. Fully populate the victim account with varied resources and document all encountered IDs. Capture all requests with the victim session.
  3. Replay each request using the attacker token with the victim's object IDs.
  4. Compare responses — same data returned = BOLA confirmed.
  5. Test unauthenticated: remove Authorization header entirely.
  6. Test write operations (PUT/PATCH/DELETE) — impact is higher than reads.
  7. Test indirect references: export endpoints, share links, scheduled jobs, email triggers.
  8. Test less-visible features: auto-save, draft, notification, audit log, attachment endpoints.
  9. Try older API versions (/v1/, /beta/) which often lack access control patches.
  10. For second-order IDOR: store a payload referencing victim's ID, trigger async processing, observe outcome.

Payloads & Tools

# ffuf: fuzz numeric IDs around your own
ffuf -w <(seq 1000 2000) -u https://TARGET/api/users/FUZZ \
  -H "Authorization: Bearer YOUR_TOKEN" -mc 200 -fs 0

# curl: direct ID swap
curl -s https://TARGET/api/orders/VICTIM_ID \
  -H "Authorization: Bearer YOUR_TOKEN"

# Append .json to bypass access control
curl https://TARGET/api/receipts/VICTIM_ID.json \
  -H "Authorization: Bearer YOUR_TOKEN"

# Try deprecated API version
curl https://TARGET/v1/users/VICTIM_ID \
  -H "Authorization: Bearer YOUR_TOKEN"
# Burp Intruder: fuzz ±1000 around your own ID
GET /api/orders/§1042§ HTTP/1.1
Authorization: Bearer YOUR_TOKEN

# JSON globbing in request body
{"user_id": [YOUR_ID, VICTIM_ID]}
{"user_id": "*"}
{"user_id": true}
{"user_id": 0}
{"user_id": -1}
{"user_id": 1235.0}

Burp extension: Autorize — automatically replaces session token with low-priv token on every request, flags unexpected 200s and response diffs.

Bypass Techniques

  • JSON globbing: replace ID with [id1, id2], *, true, 0, -1, 1234.0 — parsers may match all
  • HTTP verb swap: GET blocked → try POST, PUT, DELETE, PATCH on same path
  • Parameter pollution: ?user_id=YOURS&user_id=VICTIM — server may process last or first
  • Encoded references: base64/hex decode the ID, increment, re-encode — app trusts encoding as security
  • Alternate field names: owner_id, account_id, ref, target, resource_id, parent_id
  • Path traversal: /api/users/YOURS/../VICTIM
  • Static keyword swap: replace me or current with a numeric ID
  • Content-type switch: JSON endpoint may behave differently with application/x-www-form-urlencoded
  • Second-order: store a reference to victim's ID in a field, trigger async job that processes it without re-checking auth
  • Append extension: /resource/VICTIM_ID.json, .xml, .csv may skip access control middleware

Exploitation Scenarios

Scenario 1 — Account takeover via email change Setup: PUT /api/users/{id} accepts email as an editable field, no ownership check. Trigger: Attacker replaces their own id with victim's id in the request body. Impact: Victim's email changed to attacker's address → password reset → full account takeover.

Scenario 2 — Mass PII leak via sequential ID Setup: /api/orders/{id} returns full order: name, address, card last4, phone. Trigger: Attacker iterates integer IDs from 1 to N with their own session token. Impact: Thousands of customers' PII and payment metadata exfiltrated via scripted enumeration.

Scenario 3 — Second-order IDOR via scheduled export Setup: App lets users schedule data exports; export job runs async and emails result. Trigger: Attacker sets export_for_user_id=VICTIM_ID in the schedule request. Impact: Victim's full data export emailed to attacker — no access control on the async job.

False Positives

  • API returns 200 but with empty or redacted data — access control is working, just silent
  • Public resources (product listings, public profiles) — no authorization expected by design
  • Response identical regardless of ID — server reads from session context, ID param is ignored
  • me and current aliases that correctly resolve to the authenticated user only

Fix Patterns

-- Correct: ownership enforced at query level
SELECT * FROM orders WHERE id = ? AND user_id = current_user_id()
# Wrong: fetch then check (inefficient + race-prone)
order = db.find(id)
if order.user_id != current_user:
    raise Forbidden()

# Correct: indirect reference map (never expose raw DB IDs)
user_resource_map = {session_token: [allowed_id_1, allowed_id_2]}
if requested_id not in user_resource_map[session_token]:
    raise Forbidden()
  • Use indirect reference maps: expose opaque tokens that map server-side to real IDs
  • Centralize authorization in middleware — one place, not scattered per-route
  • Apply access control consistently across ALL HTTP methods and API versions
  • Disable or equally secure deprecated API versions

Related Skills

[[authz-bypass]] covers the broader authorization failure class — BOLA is its most common manifestation. When the application uses GraphQL, [[graphql-idor-via-introspection-leak]] shows how to enumerate the schema to find every object type accepting an ID argument. [[path-traversal]] is an IDOR on the filesystem: the same "reference to a resource without ownership check" pattern applied to file paths. IDOR findings frequently reveal [[business-logic-flaws]] — such as skipping payment by referencing another order's paid state.

From the file to a first result

The download contains exactly the content displayed on this page. This copy may differ from the latest version in the source repository.

View the source and supporting files

This download contains SKILL.md only. Any scripts, references, templates and dependencies are not included. Get the required files from the source, preserving their directory structure, before continuing.

1. Download the file

Download SKILL.md

From the root of a test project, save the file as .skill-downloads/broken-object-level-authorization-bola-idor-mrwakfou/SKILL.md, or use the command below. This folder is for inspecting the skill before installation.

Command for macOS/Linux or WSL: requires a POSIX shell and curl. On Windows without WSL, use the download button and create the folder manually.

mkdir -p '.skill-downloads/broken-object-level-authorization-bola-idor-mrwakfou' && curl --fail --show-error --location 'https://skills-guides.com/api/skills/broken-object-level-authorization-bola-idor-mrwakfou/download' --output '.skill-downloads/broken-object-level-authorization-bola-idor-mrwakfou/SKILL.md.part' && mv '.skill-downloads/broken-object-level-authorization-bola-idor-mrwakfou/SKILL.md.part' '.skill-downloads/broken-object-level-authorization-bola-idor-mrwakfou/SKILL.md'

2. Check prerequisites

Read SKILL.md before using it. If it references scripts or external services, inspect them and prepare the required access in your test environment.

Environment declared by the author: Designed for Claude Code. Burp Suite (Autorize extension) or curl recommended.

No recognized prerequisites section in this file. This does not mean it is self-contained: libraries, tools and access requirements may be mentioned elsewhere in the content or source repository.

The platforms on this page are catalog indications. The paths below follow tool documentation; they do not prove this skill has been run in those tools. No minimum tool version is confirmed for this listing.

3. Load the skill

After inspection, copy the complete folder into your project using one of the commands below, then open a new tool session. The command stops if a folder with the same name already exists: compare the files before replacing it.

Claude Code
test -f '.skill-downloads/broken-object-level-authorization-bola-idor-mrwakfou/SKILL.md' && test -s '.skill-downloads/broken-object-level-authorization-bola-idor-mrwakfou/SKILL.md' && mkdir -p '.claude/skills' && test ! -e '.claude/skills/bola-idor' && cp -R '.skill-downloads/broken-object-level-authorization-bola-idor-mrwakfou' '.claude/skills/bola-idor'

OpenSkills

OpenSkills must already be installed. The local install/read procedure is checked with OpenSkills 1.5.0, which requires Node.js ≥ 20.6.0. Catalog slugs are not resolved automatically.

Official OpenSkills installation
openskills install './.skill-downloads/broken-object-level-authorization-bola-idor-mrwakfou'

openskills read 'broken-object-level-authorization-bola-idor-mrwakfou'

Reading should display the installed file content and its base directory. It does not run the skill or install its dependencies.

For an agent that reads AGENTS.md, then sync the index. This command changes AGENTS.md: review the diff before using it.

openskills sync

Manual method or another tool: attach SKILL.md to a conversation, or open it in an agent that can read files. Include any required supporting resources. No universal folder is recognized by every tool.

4. Try a first task

Use a short, synthetic input: an API endpoint, a small document or an interface brief. In a new conversation, attach the file or give the agent its path, then adapt this request:

Read .skill-downloads/broken-object-level-authorization-bola-idor-mrwakfou/SKILL.md and apply its instructions to this example: [describe a test input]. Identify any missing files, dependencies or access. Produce the result requested by the skill without inventing data or running unreviewed scripts.

Expected result: output matching the skill instructions, or a precise list of missing prerequisites. A read confirmation alone does not validate a first use. If an external resource is unavailable, that path remains untested.

Related skills