一次请求带多组子请求的批量接口,路由和权限为什么会走错
一次请求带多组子请求的批量接口,路由和权限为什么会走错:根源通常在同一处——外层已经完成路由判定与鉴权,内层在分派子请求时直接沿用了这个结论。于是子请求既没有被当成独立请求重新路由,也没有按它自己的动作类型重新校验权限,形成「一个入口、多种能力」的混淆。
走错发生在哪一步
一次外层请求的旅程本来分四段:进入路由、解析身份、判定权限、执行处理。批量端点只在第一段和第三段做了一次判断,之后逐条执行子请求。问题就出在这个不对称上:
- 路由层面:子请求的目标能力是靠参数描述的,外层路由并不认识它,处理函数却按目标能力去调用;
- 权限层面:外层通过的是批量入口的读取或提交权限,子请求实际执行的是各自动作的权限,两者不等价;
- 上下文层面:子请求继承外层的请求上下文,包括已经解析过的路径、内容类型与身份结论。
当缺陷能把这两层混淆串到拼接查询的入口上,后果就从越权升级为远程代码执行。公开的核心缺陷通告里就有一条被直接写成批量路由混淆并导致远程代码执行,官方在致谢里同时列出了它与另一条注入问题,并在后续版本修复。
内容系统对外接口要收的三处
- 子请求按独立请求重新判定。至少重新走一次「目标能力是否允许被批量调用」与「当前身份对该动作是否有权限」,不要把外层结论当作默认通过。
- 能力清单白名单化。批量入口能触达哪些动作,应收敛成一张明确的表,而不是「凡是内部函数都能被描述到」。表外的目标直接拒绝,并记录拒绝原因。
- 参数按类型绑定。子请求参数进入查询条件时不能参与结构拼接,排序与筛选字段一律走枚举;这一条与批量与否无关,批量只是把风险面集中到了一次请求里。
审批型接口怎么配套
内置服务端子系统的接口如果允许外部客户端编排调用,权限设计要额外考虑「一次调用带多个写动作」的情形。以内容管理系统的做法为例,工具面按意图目录收敛,写操作走回合级审批并合并确认,高危域默认关闭需显式开启。这三项合起来的效果,正好堵住批量场景的两个薄弱点:能力清单可枚举,以及写动作不会因外层一次判定而被默认放行。
需要提醒的是,多站点场景下还要再叠一层:不同站点的数据与权限边界不能因为共用一套后台就互相可见,批量请求尤其要按站点归属复核。
常见问题
限制批量大小能不能规避这个问题? 不能。它只降低吞吐,不改变子请求沿用外层结论的机制。
只读接口需要重新判定吗? 需要。只读的批量入口同样可能暴露未授权的内容范围,判定成本远低于数据泄露的处置成本。
鉴权用 JWT 是不是就够了? 身份认证与动作授权是两件事。令牌证明了你是谁,不证明这个子请求对应的动作允许你执行。