MySQL注入漏洞防御,业务禁止拼接SQL语句强制预编译

MySQL注入漏洞防御的核心思路,是让SQL语句的结构与用户输入彻底分离。
所谓禁止拼接SQL语句,就是不要用字符串把用户参数直接接进SQL;
而强制预编译(预编译语句)则是把SQL模板先交给数据库解析,再把参数单独传入。
本文会从原理、代码示例、排查方法和验证步骤讲清楚。

为什么拼接SQL会成为注入漏洞?

只要用户输入被当成SQL代码的一部分,就会产生注入风险。
例如下面这段PHP代码:

$sql = "SELECT * FROM users WHERE id = " . $_GET['id'];

如果id传入1 OR 1=1,实际执行的SQL就变成:

SELECT * FROM users WHERE id = 1 OR 1=1

这会绕过条件,把整张表的数据都查出来。
更极端的还可以用1; DROP TABLE users--直接删表。

结论:只要存在字符串拼接SQL,就存在可能的注入点,改造方向就是使用预编译。

强制预编译的正确写法:以PHP PDO为例

PDO的预处理写法如下:

$pdo = new PDO('mysql:host=127.0.0.1;dbname=test;charset=utf8', 'user', 'pass', [
    PDO::ATTR_EMULATE_PREPARES => false, // 关闭模拟预处理,使用MySQL本地预处理
]);
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = :id");
$stmt->execute(['id' => $id]);
$row = $stmt->fetch();

这里的SQL模板和参数分两次传给MySQL:数据库先解析模板,再把$id作为纯值绑定。
即使$id里包含SQL语句,也只会被当成字符串处理。PHP PDO 中设置ATTR_EMULATE_PREPARES => false,才能真正落到MySQL服务端预处理。

Java后端也需要用PreparedStatement

Java JDBC中,禁止使用Statement拼接字符串,应改用PreparedStatement:

String sql = "SELECT * FROM users WHERE id = ?";
PreparedStatement ps = conn.prepareStatement(sql);
ps.setInt(1, id); // 参数通过set方法绑定,不能直接拼进sql字符串
ResultSet rs = ps.executeQuery();

如果你在用MyBatis,也要注意:#{}是预编译占位符,${}是字符串拼接。
比如WHERE id = #{id}安全,而ORDER BY ${column}存在注入风险。MyBatis中#{}是预编译,${}是拼接;
动态表名、排序字段不能预编译,必须用白名单校验。

存量业务如何排查拼接SQL?

在代码仓库里全局搜索这些特征,重点检查:

  • 字符串拼接符号:PHP的., Java的+,以及concatString.format等。
  • MyBatis XML里的${}写法。
  • 直接拼接在SQL后面的$_GET$_POSTrequest.getParameter()

Linux下可以这样在当前目录代码中搜索:

grep -rn "SELECT.*WHERE.*+" --include="*.php" --include="*.java" .
grep -rn "\${}" --include="*.xml" .

搜到后逐一改成预编译写法,不要只看报告。存量的每一个拼接点,都可能是攻击入口。

避坑与验证:这样测才算真正防御

改完代码后,在测试环境用下面的字符串尝试注入:

1' OR '1'='1
1"; DROP TABLE users; --

如果查询结果与正常输入完全一致,或直接报参数类型错误,说明拼接已被拦截。
如果出现了额外数据或SQL报错中的语法片段,说明还有拼接点没改干净。

另一个常见的坑是:预编译只能处理“值”,不能处理表名、列名、排序字段。
如果业务确实需要动态表名或排序,最稳妥的做法是做成白名单,只允许传入固定的几个值,其他一律拒绝。

如果你正在处理MySQL注入漏洞防御,业务禁止拼接SQL语句强制预编译,建议先按本文步骤完整执行,再根据自己的环境做微调;
遇到异常时优先回看避坑和高频问题部分。

分享到:
上一篇
中间人劫持HTTPS,业务强制校验证书禁止insecure跳
下一篇
备份文件泄露风险,网站目录*.sql
1
系统公告

机房迁移升级通知

尊敬的用户: IP 段 103.23.148.x、156.224.29.x 原香港一区线路波动、攻击频繁,平台定于 7 月 5 日凌晨分批迁移至香港 GIA 机房,硬件升级 AMD 铂金机型。 迁移均在凌晨操作,最大程度降低业务影响,迁移期间服务器临时关机; 升级后配置不降低、费用不涨价,数据默认同步迁移; 迁移后 IP 全部更换,请及时修改域名解析、防火墙白名单; 建议提前备份重要数据,有问题可联系在线客服。 感谢理解与支持! 泽御云科技 2026.06.30
服务中心
客服
在线客服
24小时为您服务
咨询
联系我们
联系我们,为您的业务提供专属服务。
24/7 技术支持
如果您遇到寻求进一步的帮助,请过工单与我们进行联系。
24/7 即时支持
泽御云
售前客服
泽御云
泽御云
售后客服
泽御云
技术支持
评价
您对当前页面的整体感受是否满意?
😞
非常不满意
😕
不满意
😐
一般
🙂
满意
😊
非常满意