通告写的是被助长的注入,参数拼进查询片段和拼字符串有什么差别
通告写的是被助长的注入,参数拼进查询片段和拼字符串有什么差别:差别在责任位置。拼字符串是把本该当数据的内容当成语句执行,转义勉强还能兜住;而拼查询片段是程序把「由谁决定结构」交给了请求——转义只负责数据边界,管不住结构层面的拼接。
两类写法的责任边界
| 写法 | 谁决定结构 | 转义能否兜住 | 典型参数位置 |
|---|---|---|---|
| 字符串直接拼接 | 请求内容 | 勉强能,靠字符白名单 | 搜索关键词、路径参数 |
| 参数参与查询片段 | 请求内容 | 不能,结构不是数据 | 排序字段、排序方向、按条件排除的列表 |
| 占位符绑定 | 程序 | 不涉及 | 所有取值位置 |
关键在第三列。转义解决的是「内容里有引号会不会破坏边界」,而「这段内容被当成排序子句拼进去」本身就是结构被外部决定,转义做得再完整也不会让它变安全。
为什么排除类与排序类参数最容易出问题
列表接口常提供两类能力:按字段排序、排除某些作者或分类。为了灵活,这两个参数往往被写成可以传一段表达式,再由程序拼进查询。参数名看起来像值,实际语义却是结构。以按作者做排除的那个参数为例,公开通告把缺陷成因直接写在参数上,而不是写在某个函数里,就是这个原因。
排序参数同理:字段名与方向无法用占位符绑定,只能拼进语句,所以必须在服务端做枚举收敛,把可排序字段限制在一张白名单里,非法值直接拒绝而不是转义后放行。
三层自查顺序
- 看参数是否参与结构:在代码里搜出把请求值拼进查询片段的位置,逐个判断这段内容是不是语句的一部分;
- 看是否按类型收敛:能绑定的走占位符绑定,不能绑定的走枚举白名单,两者都不做的视为缺陷而不只是风格问题;
- 看错误信息是否回显结构:把片段内容打印进响应或日志,会让判定难度骤降,生产环境应关闭这类回显。
内容系统里该盯的入口
文章列表的排序参数、筛选条件与批量操作入口,都属于「参数决定结果集形状」的位置,是最需要复查的一类。内容管理系统在这一层有过实际修复记录:v3.6.6 处理了列表排序参数注入问题,配套还修掉了站点切换时登录凭证可被伪造的缺陷。升级这类系统时,除了装上修复版本,还要把对外暴露的列表参数重新过一遍——防御能力(包括 JWT 认证、敏感词过滤与针对 SQL 注入、XSS 的处理)解决的是默认路径,自定义扩展与模板里手写的查询仍然在自己手上。
常见问题
只用框架提供的查询构造器就安全了吗? 不一定。构造器里也有允许传入原始片段的接口,一旦这些接口接收请求值,结构就又交出去了。
转义和参数绑定能同时用吗? 可以,但作用不同。绑定处理数据,白名单处理结构;把转义当成结构防护是常见误解。
被助长的注入算不算高危? 要看可达路径与认证前提。若参数在无需登录的列表接口上被直接拼接,应当按高危处置。