「把 URL 里的 id=124 改成 125,就显示出了他人的发票」——这就是 IDOR(访问控制缺陷)。本文讲解其原理与可靠的防范方法(不会写出攻击步骤)。
为什么会发生
明明「认证(你是谁)」已经通过,却缺了「授权(这个人是否可以操作它)」时就会发生。认证与授权是两回事,能登录并不等于可以查看那份数据。
| 常见的疏漏 | 后果 |
|---|---|
| 登录后就直接信任 ID | 改成他人的 ID 就能轻易绕过 |
| 误以为「界面上不显示=安全」 | 一旦被直接调用 API 就毫无防备 |
| 创建/更新/删除没有权限校验 | 不仅能查看,还能篡改、删除 |
为什么会成立(原理)
防御:在服务端每次确认「所有者与权限」
针对每个对象校验所有者与权限(最重要)
在返回/变更数据的紧前一刻,必须在服务端校验「当前登录的用户 ID,是否为该对象的所有者、是否拥有操作权限」。不满足则拒绝。
默认拒绝(deny by default)
新的端点应以「除明确许可的条件外一律拒绝」为初始状态,让漏加校验时倒向「拒绝」一侧,而非「放行」一侧。
只查询「属于自己的」对象
在查询语句本身中就带上所有者条件(例如:用户 ID=本人 来筛选)。统一走全应用通用的授权辅助函数,杜绝各处的遗漏。
不要把界面控制误当成防御
隐藏/不显示按钮属于 UX,而非防御。要以「API 会被直接调用」为前提,只在服务端做判断。随机 ID 只能作为辅助。
本站的观点:虽不花哨,但危害极大。用测试来「盯紧」它
IDOR 在技术上很朴素,连代码评审也容易漏看。然而「一次点击就能看到他人全部个人信息」这类危害规模属于最高级。正因如此,把「用另一个用户去访问他人的 ID,是否返回 403」固化进自动化测试才是更贴近实战的做法。本站坚持「不靠客户端的外观来防守/只在服务端做判断」的原则。授权是「靠机制每次都生效」的东西,关键在于不依赖人的注意力。
接下来阅读
- 术语:CSRF 是什么(认证与授权的区别)
- 入门:安全超入门 / 免费安全工具
FAQ
QIDOR 会发生什么?
已登录的用户,仅靠把 URL 或 API 中的 ID(如 ?id=124)改成另一个值,就能查看、修改、删除他人的发票、订单、个人信息、文件等。它是 OWASP 中最常见的问题类别(访问控制缺陷)的代表,可怕之处在于无需任何特殊工具就能发生。
Q最主要的防御是什么?
就是「在服务端每次确认『当前登录的这个用户,是否可以操作该对象』」。即使 ID 形式正确,也必须校验它是否为本人所有、是否拥有权限,不满足则拒绝(默认拒绝)。绝不能只依赖客户端的界面控制。
Q把 ID 改成 UUID 或随机值就能防住吗?
那只是「让它更难猜」,并非根本对策。一旦 ID 被泄露或被分享出去就会被轻易绕过。随机化只能作为辅助,关键一定要落在服务端的所有者与权限校验上。