SQL 注入:参数化查询为什么能根治
SQL 注入不新鲜,但每年仍在 OWASP 前十。原因不是大家不知道,而是「拼接更方便」。
理解一个点就够了:只要用户输入进入了 SQL 语句的语法结构,就有注入风险——不管它看起来多安全。
先说结论
所有变量走参数化,排序/表名走白名单,数据库账号只给必要权限。
- 参数化查询让数据库把输入当数据而非语法
- ORDER BY / LIMIT / 表名无法参数化,必须白名单
- ORM 的 raw 查询是重灾区
- 数据库账号禁止 FILE/SUPER 权限
漏洞是怎么产生的
SQL 的解析分两步:先编译语法结构,再代入数据。拼接字符串会让用户输入参与到第一步,于是 ' OR 1=1 -- 变成了语法的一部分。
参数化查询把「结构」和「值」分开传给数据库,结构先编译,值只当数据。这是从机制上杜绝,不是过滤。
修复与验证
修复不是改一行代码,而是四件事一起做:
- 全量排查拼接 SQL:搜索字符串拼接 + 查询执行的位置
- 改为参数化(占位符),包括 IN 列表的动态占位
- 排序字段、表名、列名改为枚举白名单映射
- 检查 ORM 的 raw/execute 调用,同样要参数化
- 数据库账号降权:只授予业务需要的 SELECT/INSERT/UPDATE/DELETE
攻击面与检测点
按影响面排序,先修影响最大的:
| 入口 | 风险点 | 修法 |
|---|---|---|
| 查询参数 | 拼接 WHERE | 参数化占位符 |
| 排序/分页 | ORDER BY 拼接 | 白名单映射 |
| 搜索框 | LIKE 拼接 | 参数化 + 转义通配符 |
| ORM raw | 原生 SQL | 参数绑定 |

几个容易踩的坑
下面这些是最常见的错误做法:
- 用 addslashes/转义代替参数化:宽字节与数字型仍可绕
- 只在前端校验:抓包即可绕过
- 过滤 select 关键字:注释、大小写、编码都能绕
- 忽略二次注入:数据入库后再拼接
写在最后
判断标准很简单:代码里还有没有「变量拼进 SQL 字符串」。有就改,别讨论是否可利用。
安全不是一次加固,是持续的假设:假设输入不可信、假设边界会破、假设有人会看错。
评论 (3)
修复清单比漏洞描述有用多了,很多文章只讲怎么打不讲怎么防。
白名单那条永远是最有效的,正则黑名单迟早绕过。
建议再补一条:把这类检查加到 CI 里,靠人记必然漏。
发表评论