3.3 授权模型:RBAC、ABAC、ReBAC 与资源级检查
认证确认主体,授权决定主体在当前上下文能对具体资源执行什么动作。很多越权漏洞并不是没有登录,而是应用只检查“已登录”或“拥有某角色”,没有检查目标对象与主体之间的关系。
一次决策至少有四个输入
allow? = policy(subject, action, resource, context)- subject:用户、服务、设备及其组织、角色、认证保证;
- action:read、update、approve、transfer,而不只是 HTTP method;
- resource:具体订单、项目、字段、租户与当前状态;
- context:时间、网络、设备风险、变更窗口和请求来源。
安全默认是 deny。没有匹配允许规则、策略数据缺失、策略引擎超时或身份不确定时,都不应悄悄放行高风险操作。
RBAC 管理稳定的工作职责
user → role → permissionsRBAC 适合“审计员可读报告”“发布经理可批准发布”一类稳定职责。角色应表达业务责任,而不是每个页面创建一个角色。若出现 admin-east-read-except-finance-temp 这类组合爆炸,说明还需要属性或关系。
避免把 admin 写成绕过所有授权的布尔值。高权限操作也应有明确 action、范围、重新认证和审计,并允许拆分日常账户与临时提权会话。
ABAC 用属性表达动态约束
ABAC 可以组合:
subject.department == resource.department
AND resource.classification <= subject.clearance
AND context.time within approved_window2
3
它表达力强,但属性本身需要可信来源、类型、时效和所有者。若用户能修改自己的 department claim,策略再漂亮也没有意义。策略语言应有测试、变更评审和可解释决策日志,避免散落在几十个 controller 的条件分支中。
ReBAC 描述主体与对象关系
协作文档、代码仓库和社交产品常依赖关系:
user:lin is member of team:atlas
team:atlas is editor of project:north
therefore user:lin can edit document:x in project:north2
3
ReBAC 能表达继承、共享与组织图,但需要控制图遍历深度、循环、缓存一致性和关系撤销延迟。把对象 ID 从 17 换成 UUID 只能降低枚举便利,不能替代每次资源访问的关系检查。
IDOR/BOLA 来自缺失的资源级授权
危险流程:
GET /orders/8172
→ 验证用户已登录
→ SELECT * FROM orders WHERE id = 8172
→ 返回2
3
4
安全查询应尽早把授权范围纳入数据访问:
SELECT ...
FROM orders
WHERE id = :order_id
AND tenant_id = :principal_tenant
AND owner_id = :principal_id;2
3
4
5
更复杂权限可先由 policy engine 得出允许范围或关系,再查询对象。无论采用哪种架构,列表、详情、更新、导出、批量接口和后台任务都要执行一致检查。只在前端隐藏按钮没有任何安全价值。
多租户边界应贯穿全链路
Tenant 不能只来自客户端 header。应从已验证身份和服务端路由上下文确定租户,并在数据库查询、缓存 key、对象存储 path、队列消息、搜索索引和日志访问中传播。
缓存若只用 resource_id,可能把 A 租户对象返回给 B;后台 worker 若信任消息中的 tenant 而不验证任务签发者,也会跨边界执行。租户隔离是数据模型与执行上下文属性,不是 API gateway 的一个过滤器。
Confused Deputy:有权限的服务被借来做坏事
某个转换服务有权读取所有对象,用户提交任意 source_url 后让它代读内部管理地址,这个服务就成了 confused deputy。防护包括:
- 代表用户调用下游时传递或换取受限 delegated credential;
- 将 audience、resource、action 和租户绑定到 token;
- 服务自身权限与代表用户的权限取交集;
- 不接受任意资源引用,使用服务端解析与 allowlist;
- 对跨边界操作保留原始主体链和审计。
策略集中不等于单点远程调用
可以把策略定义集中到版本化 policy repository,同时根据延迟与可用性选择 sidecar、嵌入式 evaluator 或本地缓存。必须明确:
- policy decision point 不可用时哪些动作 fail closed;
- policy 和关系数据多久传播,撤权窗口多长;
- cache key 是否包含主体、资源、动作、tenant 和 policy version;
- 决策日志是否记录输入摘要、规则版本和结果,又避免泄露秘密;
- 紧急 deny 是否有比普通发布更快的分发路径。
高风险动作还可使用 just-in-time elevation:短期、限定资源、需要审批,过期自动撤销。永久超级管理员既扩大攻击面,也让审计很难区分日常与紧急操作。
授权测试矩阵
正向:正确主体可以执行允许动作
横向:同角色用户不能访问别人的资源
纵向:普通用户不能执行高权限动作
跨租户:任何资源引用都不能越过 tenant
状态:已关闭/冻结对象拒绝原本允许的动作
撤权:关系或角色撤销后,在约定窗口内生效
故障:策略服务/属性源不可用时按设计失败
批量:列表、导出和异步任务与单对象检查一致2
3
4
5
6
7
8
认证强度再高,也不会自动产生正确授权。把资源级检查放进服务端可信边界,并让策略可测试、可解释、可撤销,才是权限系统真正的骨架。
参考资料
- NIST, Guide to Attribute Based Access Control
- OWASP, Authorization Cheat Sheet
- OWASP API Security, Broken Object Level Authorization