IDOR 不安全的直接对象引用:API 越权实战检测

API 越权里,出镜率最高的名字之一叫 IDOR(Insecure Direct Object Reference,不安全的直接对象引用)。名字有点学院派,翻译成人话却很土:

你拿着自己的登录态,把请求里的"对象编号"改成别人的,服务器居然把别人的东西给你了。

订单号、用户 ID、文件 ID、商户 ID、工单号、uuid 看起来很随机......只要服务端没有认真问"这个对象属于你吗",改编号就可能得手。扫描器对这类洞经常哑巴------它不懂"10086 是你的、10087 是他的"。所以 IDOR 几乎成了人工测试与业务安全的自留地。


一、IDOR 到底在说哪一种越权

1. 经典定义

应用使用用户可控的标识(ID)直接访问对象,却缺少或失败于授权校验,导致访问了未授权对象。

"直接对象引用"可以是:

  • 数字 ID:/orders/1024
  • UUID:/files/550e8400-e29b-41d4-a716-446655440000
  • 文件名:/download?name=contract.pdf
  • 预签名 URL 中的路径参数(若权限模型错误)
  • GraphQL 的 id 参数

UUID 降低枚举,不自动消灭 IDOR------你若仍能通过泄漏的 UUID 访问他人对象,那仍是授权失败,只是攻击面从"遍历"变成"泄露后利用"。

2. 水平 vs 垂直

类型 含义 例子
水平越权 同级用户互访对方资源 A 看 B 的订单
垂直越权 低角色访问高角色能力/资源 普通用户调管理删除
未授权 没登录也能访问 游客看需登录数据

IDOR 最常指水平对象级越权;广义报告里也有人把"改 role 参数"写成 IDOR,更严谨应写垂直越权/失效访问控制。检测手法高度重叠,定性时尽量准确。

3. 和"失效的访问控制"的关系

OWASP A01 大类下,IDOR 是最具体、最好教的一种。修好 IDOR,不等于访问控制满分,但能消掉一大片真实事故。


二、为什么 API 是重灾区

1. 前后端分离

前端不展示的按钮,API 依然在。移动端、小程序、第三方还共用一套后端。攻击者直接打 API,不走你的页面流程。

2. 对象 ID 满天飞

REST 风格天然 /resource/{id}。列表接口先返回一堆 ID,详情接口再按 ID 取------若详情只验登录,IDOR 就成了"列表当字典 + 详情当仓库"。

3. 微服务与网关

网关验了 JWT,下游服务以为"网关都验了就信任",只按 ID 查库。身份传到了,授权没传到。

4. 批量与导出

/orders?ids=1,2,3、导出任务、消息推送预览------一次越权一片数据。

5. 非 JSON 的"旁路对象"

PDF、发票、附件下载、WebSocket 订阅频道名、对象存储 key------都是对象引用,都要鉴权。


三、实战检测总流程(建议背下来)

text 复制代码
① 准备账号矩阵(A/B,必要时商户/管理员)
② 摸清对象与 ID 出现位置(列表、推送、导出)
③ 对每个"带 ID 的读/写/删"做换绑测试
④ 扩大到批量、导出、下载、共享链接
⑤ 记录证据、定级、清理、回归用例化

核心动作就一个字:------换 ID、换账号、换角色、换租户。


四、账号与环境准备

1. 至少两套同级账号

A、B 权限相同,数据隔离。分别制造自己的订单/文档/消息。

记下:A 的 order_id、B 的 order_id

2. 再加角色更好

普通用户、商户、运营、管理员------垂直问题一起捞。

3. 租户/组织

SaaS 多租户测 org_idtenant_id 是否可改。这是 IDOR 的亲戚,常叫跨租户越权。

4. 工具

代理(Burp 等)、两个浏览器配置、可选的自动化脚本(只在授权范围)。

别对生产狂暴遍历 ID,以免触发风控或造成数据压力。


五、发现"对象引用"的实战技巧

1. 从列表到详情

登录 A,打开列表,抓详情请求。所有像 ID 的参数列成表:路径参数、Query、Body、Header(少见但有)。

2. 从 JS 与 APP 里挖隐藏 API

前端路由、Webpack 里的 /api/、旧版接口。隐藏的 getUserById 往往鉴权更嫩。

3. 从通知与邮件挖 ID

邮件链接、短信链接、推送 deep link 带长 ID------测这些 ID 是否可在未分享情形下被他人使用。

4. 上传与下载

上传返回 fileId,下载 GET /file/{fileId}。用 B 的 token 下 A 的 fileId。

5. GraphQL / RPC

query { order(id: ...) { ... } }

mutation 里的 id。GraphQL 一次查询多字段,越权危害更大,检测逻辑一样:换 id + 换身份。


六、检测动作详解

1. 水平读越权(最常见)

  • A 登录,访问 A 对象,存响应指纹(姓名、金额、标题);
  • 同一请求,把 ID 改成 B 的,仍用 A 的 Token;
  • 若返回 B 的指纹 → 读 IDOR 成立。

注意:有的返回 200 但空数据/统一报错,要区分"无权限"和"对象不存在"。以敏感字段是否出现为准。

2. 水平写越权

改地址、改订单备注、取消订单、修改共享权限。

用 A 的身份提交 B 的 ID。写成功比读成功更严重。

3. 删除与状态变更

删除别人的评论、归档别人的项目。状态机类操作都要测。

4. 创建时指定他人 ID

创建订单时 body 带 userId;创建子账号时指定 orgId。属"引用绑定越权"。

5. 批量接口

ids[]=B的iduser_ids 列表。部分成功也要报。

6. 函数级:导出与异步任务

创建导出任务时带筛选条件,任务结果是否可被另一用户的 task_id 下载。

异步世界的 IDOR:task_idjob_idreport_id

7. 存储与 CDN

返回的 URL 是否永久有效、是否无额外鉴权、是否可猜。

预签名过期短、且绑定权限,才有意义。

8. 编码与间接引用

ID 经 Base64、加密------若可解密或可替换密文仍过,继续测。

"加密 ID"不是授权。


七、自动化检测:能做多少、不能指望多少

1. 半自动

插件协助替换 ID、对比响应相似度,能提速。仍需人定义"哪些是对象"。

2. 基于流量的差分

用 A、B 账号分别爬业务,自动尝试交叉 ID。对标准化 REST 有效,对复杂业务易误报漏报。

3. 为什么很难全自动

  • 不知道"同级对象"集合;
  • 不知道响应里哪段算敏感成功;
  • 验证码、验证码、步骤码打断;
  • 合法共享会导致误报(A 本就可看 B)。

结论:IDOR 检测以方法论固化的人工/半人工为主,自动化是帮手。


八、合成案例集(方便内训)

案例 1: 医保/电商订单详情 IDOR,泄露地址电话。

案例 2: 工单系统附件 fileId 可跨员工下载。

案例 3: 多租户 SaaS 改 tenant_id 读他租户报表。

案例 4: GraphQL user(id) 无授权指令。

案例 5: 导出任务 ID 可枚举下载。

案例 6: 对象存储 key 来自接口,下载接口未二次鉴权。

案例 7: "分享链接"永久有效且无密码,等于公开 IDOR。

案例 8: 修改收货地址接口可改他人 address_id

每个案例的检测动作都是:双账号 + 换引用 + 看是否成功。


九、定级建议

情况 级别参考
可读大量 PII / 证件 / 订单 高危~严重
可写/删除他人关键对象 严重
跨租户数据 严重
仅可读非敏感公开类对象 中低(视业务)
需先获取机密 UUID 且难泄漏 仍要修,可注明利用条件

"ID 难猜"不能当作接受风险的唯一理由,尤其当 ID 会在列表、日志、推送、Referer 里泄漏时。


十、修复与架构级解法

1. 服务端强制鉴权(根治)

伪代码思维:

text 复制代码
obj = load(id)
if obj.owner != current_user and not has_perm(...):
    deny

每个对象类型集中写策略,避免每个 Controller 手写漏掉。

2. 统一授权中间件 / 策略引擎

基于注解:@PreAuthorize、自定义 checkOrderAccess(orderId)

GraphQL 字段解析器同样要挂授权。

3. 避免可信客户端

不要信 body 里的 userId 当所有者;所有者取自会话。

4. 间接引用可作辅助

每用户映射表、短时 tokenized reference------减枚举。仍需鉴权。

5. 批量接口

逐个做授权过滤;无权的 ID 不返回、不计入。

6. 下载与文件

鉴权后流式输出;或短时预签名且绑定用户与对象。

7. 多租户

所有查询带 tenant_id = current_tenant 强制条件(行级安全),禁止客户端传租户覆盖。

8. 日志与监控

授权失败告警;异常批量 403/交叉访问模式。

9. 测试门禁

CI 中集成双账号 API 测试:A token + B id → expect 403。

这是防回归最有效的手段。


十一、检测工作检查单(可直接贴到项目)

准备

  • A/B 账号与各自对象 ID
  • 代理可改包
  • 范围与生产安全阀

覆盖

  • 详情读
  • 更新/删除
  • 批量
  • 导出/异步任务
  • 附件下载
  • GraphQL/RPC
  • 租户字段
  • 分享链接

证据

  • 请求/响应(脱敏)
  • 两个账号对比
  • 复现步骤

收尾

  • 通知开发
  • 补回归用例
  • 复测关闭

十二、常见翻车与误报

误报: 家庭共享、企业委托、医生看病人------本身有授权关系。要先懂业务。

漏报: 只测了读,没测写;只测了 REST,没测下载;只测了数字 ID,没测任务 ID。

假修复: 前端隐藏 ID;改成 UUID 但仍不鉴权;仅网关验登录。

假安全: "我们 ID 是加密的"。


十三、收尾

IDOR 的检测没有神秘公式,只有重复一千次仍然有效的动作:

用自己的身份,访问别人的对象引用。

API 让这个动作更简单,也让疏漏更致命。防住它也不靠改成 UUID 的心理安慰,而靠每一条对象访问链路上的强制授权,以及双账号回归测试这道门禁。

今晚若只做一件事:选一个最核心的详情 API,准备两个账号各造一条数据,把 A 的 token 配上 B 的 id 打一次。

200 且是 B 的数据------恭喜你挖到了真洞;403------恭喜你们对象鉴权可能真的在线。无论哪种,你都已经在做"API 越权实战检测",而不是在背 IDOR 的英文全称。


附:快速对照

问题 检测动作 修复
水平读 A token + B id 对象级鉴权
水平写 A token 改 B 对象 同上 + 审计
批量 混入他人 id 逐条过滤
下载 换 fileId 鉴权后输出
租户 改 tenant_id 强制租户条件
相关推荐
堕落年代1 小时前
Ollama CPU 推理大提示词优化实测报告(细致化数据版)
java·后端·spring
c238561 小时前
# Mini OJ — 项目详解文档
开发语言·数据库·c++
上海云盾-小余1 小时前
2026 网站基础防护指南:新手搭建低成本安全体系全过程总结
安全
2401_894915531 小时前
Geo 优化源码部署常见报错排查:连接失败、地图加载、地域词失效解决方案
服务器·开发语言·python·安全·php
c238562 小时前
C/C++每日一练20
c语言·开发语言·c++
KobeSacre2 小时前
ForkJoinPool 源码
java
wear工程师2 小时前
Kafka 消费者心跳正常,为什么还会被踢出组?拆清 max.poll.interval.ms
java·kafka
SemiTris2 小时前
为什么 C/C++ 不走 Java 式的虚拟机跨平台路线?
java·程序员
WHS-_-20222 小时前
基于网络感知自适应树与辅助路由加速地理分布式机器学习
网络·分布式·机器学习