越权访问是什么
越权访问指系统只验证了「你已登录」,却没有验证「这条数据是否属于你」。接口用订单号、文件 ID 这类直接对象标识查询数据,服务端不校验归属,攻击者把标识换成别人的值就能读到或改到他人数据,这类问题通常称为 IDOR(不安全的直接对象引用)。另一种形态是垂直越权:普通用户能访问管理员功能,成因是权限判断只做在前端菜单或网关层。它的特点是数量密集、发现容易,一旦存在往往整站同类接口都有。
基本信息
| 风险类别 | OWASP Top 10 2021 A01 失效的访问控制;CWE-639 |
|---|---|
| 主要形态 | 水平越权(同角色跨用户)与垂直越权(低权限访问高权限功能) |
| 成因 | 只校验登录态不校验归属,信任前端传入的身份或权限字段 |
| 常见位置 | 详情与下载接口、批量接口、导出接口、GraphQL 节点查询 |
| 危害 | 批量读取他人数据、篡改与删除他人数据、越权执行管理操作 |
| 修复要点 | 服务端强制归属校验,查询条件带当前主体,权限判断不可下放前端 |
常见出问题的地方
- 订单、工单、发票的详情与下载接口,按 ID 直接查询
- 用户资料与地址的修改接口,只校验登录不校验归属
- 文件与附件下载,路径或文件 ID 可枚举
- 批量操作与批量导出,循环里逐条查询但不做归属过滤
- 管理功能接口挂在普通用户可访问的路由下,仅前端隐藏入口
- GraphQL 或开放 API 通过节点 ID 查询,授权逻辑分散在各解析器中
- 第三方回调与消息队列消费接口,按消息中的 ID 直接落库
风险与修复对比
风险与修复对比
风险:/api/orders/12345 仅按 id 查询,未校验归属
修复:查询条件强制带归属:
SELECT * FROM orders WHERE id = ? AND user_id = ?
或在访问前显式执行权限判断
# Java 示例:Order o = repo.findByIdAndUserId(id, currentUserId)
# 中间件示例:统一在路由层绑定当前主体,禁止直接用前端传的 userId
# 关键原则:授权判断放在服务端数据访问路径上,而不是页面渲染时排查清单
排查清单
遍历接口中的资源 ID 参数(订单、发票、文件、地址…)
确认每个读写点都有归属校验
批量接口、导出接口同样覆盖
越权测试:用 A 账号访问 B 账号资源(授权测试范围内)
检查参数里是否出现 userId、role、tenantId 等可篡改的身份字段
检查返回对象是否包含不该看到的字段(脱敏与最小化返回)两种越权形态对照
| 形态 | 表现 | 验证方式 |
|---|---|---|
| 水平越权 | 同角色读取或修改他人数据 | 用 A 账号请求 B 账号的资源 ID |
| 垂直越权 | 低权限角色可调管理接口 | 用普通账号直接请求管理端接口 |
| 混合形态 | 先越权拿到管理员 ID 再读其数据 | 组合多步请求验证数据边界 |
前端隐藏入口不构成防护:直接请求接口即可绕过,权限判断必须在服务端完成。
换成 UUID 或加密 ID 只是提高猜测难度,属于缓解手段;缺少归属校验时,任何 ID 形式都挡不住越权,且标识一旦从日志或分享链接泄露就会失效。