是什么

IDOR(Insecure Direct Object Reference,不安全的直接对象引用):应用使用用户提供的输入直接访问对象,而没有做权限校验。

结果:用户可以访问本不属于自己的资源。

简单例子

一个查看订单的 API:

GET /api/orders/10086

服务器返回订单 10086 的详情。

问题:服务器只根据 URL 中的 ID 返回数据,没有检查这个订单是否属于当前用户。

攻击:把 ID 改成 10087、10088……就能看到其他用户的订单(含姓名、地址、电话、购买内容)。

只是改一个数字——这就是 IDOR。

常见形式

一、数字 ID 递增:最容易发现和利用。

二、UUID/GUID:不那么容易猜测,但如果 UUID 在别处泄露(如共享的链接、日志),IDOR 依然存在。

IDOR 的本质是"缺少授权检查",与 ID 是否可猜测无关。

三、文件名/路径:

GET /download?file=report.pdf
GET /download?file=../../../etc/passwd

(后者还涉及路径穿越。)

四、其他标识符:用户名、邮箱、手机号、订单号等。

与其它概念的关系

水平越权:同级别用户之间的越权(用户 A 看用户 B 的数据)。

垂直越权:低权限用户访问高权限功能(普通用户访问管理员接口)。

IDOR 通常指前者,但两者都是访问控制失效。

OWASP 将"访问控制失效"列为 Web 应用安全的顶级风险之一。

防御

一、在每个数据访问点做授权检查(根本)

原则:不信任任何来自客户端的标识符。

1. 从会话/令牌中获取当前用户 ID(**不能**从请求参数中获取)
2. 查询请求的订单
3. 检查 order.user_id == 当前用户 ID
4. 不匹配 → 返回 403 或 404

注意:

  • 当前用户的身份必须从服务端可信来源获取(session、签名 JWT),而不是请求参数中的 user_id=123;
  • 检查应该在数据访问层做,而不只是 UI 层(隐藏按钮不等于安全)。

二、使用不可猜测的标识符(缓解,非解决)

用 UUID 替代自增 ID 可以增加利用难度,但不能替代授权检查。

三、间接引用映射

为每个用户维护一个"用户特定的引用"到"真实对象"的映射。用户只能看到自己的映射。

这增加了一层防护,但实现更复杂。

四、集中式的访问控制

不要在成千上万个 API 端点中各自写检查——容易遗漏。

做法:在框架层面(中间件、装饰器、ORM 层)统一实施访问控制。

五、自动化测试

  • 编写针对越权的测试用例:用用户 A 的凭据访问用户 B 的资源,应该失败;
  • 在 CI 中运行;
  • 渗透测试中专门覆盖这一项。

检测

手工测试:

  1. 用账号 A 登录,创建一个资源,记下其 ID;
  2. 用账号 B 登录,尝试访问该 ID;
  3. 如果能访问 → 存在 IDOR。

工具:Burp Suite 的 Autorize 插件等,可以自动化对比不同权限下的响应。

一个真实影响

IDOR 是最常见且危害直接的漏洞类型之一:

  • 直接导致用户数据泄露(个人信息、支付记录、医疗数据);
  • 利用门槛极低(改个数字就行)——自动化扫描器也能发现;
  • 在 API 化的应用中尤其普遍。

它对开发者的提醒:"能找到资源"不等于"有权访问资源"。 每次返回数据前,都要问一句"这个人该看到这个吗?"

说明:本文为 Web 安全的知识整理。