SQL 注入是老而常新的漏洞:攻击面集中在把用户输入拼进 SQL 语句的写法上,防御方案成熟且成本极低,但每年仍有新系统栽进去。从原理层面理解参数化查询为什么有效,比背规则更可靠。
## 注入的原理
拼接式写法把用户输入直接嵌进 SQL 文本,输入的内容因此获得了被数据库解释的机会。用户名输入框里填入构造好的片段,与原有语句拼接后形成了全新的语义:原本的等值判断可能变成恒真条件绕过登录校验,或者追加查询、注释掉后续条件。关键点在于:数据库无法区分哪部分是程序意图、哪部分是用户输入,它只看到一整条语句。
## 参数化为什么有效
参数化查询把语句结构与数据分离:SQL 文本先行发送到数据库完成解析,占位符的位置与语句结构被确定下来;用户输入随后作为纯数据绑定到占位符,不再参与语法解析。无论输入什么内容,它在数据库眼里都只是一个字符串值,不可能改变语句结构,注入的土壤被连根移除。
python
# 参数化查询,输入只作为数据
cursor.execute("SELECT id, name FROM users WHERE name = %s", (username,))
## 常见错误
第一种是半吊子参数化:查询用占位符,排序字段、表名这类无法占位的位置直接拼接,攻击者从这些位置照样能注入,白名单校验是这些位置的标准解法。第二种是迷信 ORM:ORM 默认方法安全,但手写原生查询的接口一旦拼接输入,风险原样回归。第三种是依赖过滤:黑名单过滤永远在追赶新的绕过姿势,转义函数用错上下文等于没转义,参数化才是根本。第四种是忽视权限兜底:应用账号只授必要表的必要权限,即使被注入,破坏面也被数据库层拦住一道。
## 收束
防御清单很短:查询一律参数化,无法占位的位置用白名单,应用账号最小权限,错误信息不回显数据库细节。顺云的云服务器承载各类数据库负载,这四条纪律落实在代码与账号配置层,注入这个最老牌的攻击面就基本关闭了。