参数被拼进动作名里会出什么问题,这类命名拼接怎么自查
请求参数被拼接成内部动作名或钩子名时会出现什么问题,站内该怎么自查?会出现的是「触发到没打算暴露的动作」:名字是拼出来的,能拼出合法名字的输入,就能挂到别的处理逻辑上。同行系统 WordPress 在 2026 年 10 月的安全维护版本里修了这一类:传入状态与类型拼接钩子的参数可被伪造,导致动作名冲突,由 WordPress 安全团队的 Alex Concha 报告。公告只写了成因与结果,没有写具体利用方式,自查按成因做就够。
拼名字这种写法为什么会带来越权
内部动作名常见形式就是「状态加类型」或「对象加动作」,中间用一个分隔符连起来。注册监听时按这个规则生成名字,调用时也按同一个规则拼出来——看起来对称、省事。
问题在调用侧的值来自请求。若参数可以直接影响拼出来的名字,调用方就在替系统选择「走哪个已注册的处理」。而监听注册表往往比对外接口大得多:内部清理、状态回退、批量重算这类动作都在里面,它们本来假定只由系统内部调用,没做二次鉴权。
越权不是靠绕过校验得到的,而是靠「这个名字竟然可被外部叫到」得到的。这是拼接写法最典型的后果。
动作名冲突和参数注入是不是一回事
不是一回事,但成因同源。参数注入是值被当成代码执行,动作名冲突是值被当成路由标识。前者后果常落在数据层,后者后果常落在行为层。
两者的共同点是:拼接发生在校验之前,或者根本没有校验。所以处理方式也一样——不是给拼接加转义,而是把可取值枚举出来。
自有系统的同类修复可以作为对照:AnQiCMS v3.6.6 修的一项高危问题是列表排序参数被拼进查询语句,另一项是站点切换时登录凭证可被伪造,依据是一次性票据的签发方式;升级建议里同时要求轮换服务端签名密钥并修改管理员密码。排序参数与拼接是两个不同层面(查询语句与动作名),但风险模式一致:本应是枚举值的参数,被当成了自由字符串。
站内的三类拼接点怎么排查
第一类是钩子与动作名。搜所有把变量**名字模板的位置,看模板的变量段来自哪里。只要有一段来自请求,就列进整改。
第二类是路由与页面标识。「按参数拼出模板名」「按参数选择处理分支」这类写法后果和动作名冲突相似,区别只在能触达的处理范围。排查方式相同:模板名与分支标识必须由白名单决定。
第三类是查询构造。排序字段、表别名、状态筛选这类参数若被直接拼接,就成了数据层的问题。这一类要按参数化处理,而不是按字符过滤——过滤永远比不过白名单。
三类排查完,把结果落成一张表:参数名、允许值、校验位置、是否有白名单。表格比代码注释更容易在下次改动时被沿用。
文档状态与类型参数该按白名单校验
状态与类型是最常见的两个拼接段,也最容易被当成自由字符串传。原因是这两者在界面上看起来「怎么传都行」。
按内容状态举例,站内的文档状态本身是有限集合:正式文档、草稿、待发布、回收站四类。AnQiCMS 的处理口径就是这样——草稿链接带预览标记可预览,删除正式文档是移入回收站而不是物理删除。既然取值固定,校验就应该按枚举做:不在集合内的值直接拒绝,而不是拼进名字后看会不会命中。
类型字段同理。自定义内容模型下的类型标识由后台定义,前台请求没有理由带任意类型进来。
写成校验函数时注意两点:白名单要放在服务层而不是只在控制器;拒绝要产生明确错误,而不是「什么都不发生」——什么都不发生会让排查者误判为逻辑失效。
常见问题
只改分隔符转义行不行? 不行。转义挡不住合法拼接出的其他名字,冲突照样发生。要挡的是可选值范围。
内部动作要不要都收进来? 建议按可达性收:外部可达的入口只保留白名单动作,内部动作由系统调用。范围一旦收窄,拼错名字的后果就从越权退化成找不到动作。
怎么确认历史版本有没有被这样调用过? 查日志里参数值的分布最省事:把状态与类型两个参数的取值列出去重,出现集合外的值就说明有人这样调用过,或曾经被这样试过。
修复上线后还要做什么? 按公告口径执行到位。写了轮换服务端签名密钥与修改管理员密码的,两项都要做完;只替换代码不轮换,凭证类的风险仍在。