mysql_query本身不防注入,因其仅原样执行传入字符串,无参数占位、无类型校验、不区分代码与数据,导致用户输入如' or '1'='1可直接篡改sql逻辑。

直接拼接用户输入进 mysql_query 的 SQL 字符串,且不做参数绑定或类型校验,就是最典型的触发路径。
为什么 mysql_query 本身不防注入
mysql_query 只负责把传入的字符串原样发给 MySQL 执行,它不管里面有没有单引号、分号或注释符。它既不解析 SQL 结构,也不检查变量来源——你塞进去什么,它就执行什么。
- 它没有内置参数占位符机制(不像
PDO::prepare或mysqli_prepare) - 它不区分“代码”和“数据”,
$_GET['id']和硬编码的1在它眼里都是字符串 - 一旦用户输入包含
' OR '1'='1这类内容,拼出来的整条 SQL 就被逻辑篡改了
常见错误写法:字符串拼接 + 未过滤输入
这类代码现在仍大量存在于老旧项目或新手练习中:
$id = $_GET['id']; $sql = "SELECT * FROM users WHERE id = '$id'"; mysql_query($sql);
问题不止在单引号闭合——数值型字段也危险:
$id = $_GET['id']; $sql = "SELECT * FROM users WHERE id = $id"; // 没引号?照样能输 `1 OR 1=1`
- 即使
magic_quotes_gpc = On,它只逃逸单双引号和反斜杠,对数字上下文无效 -
addslashes()或mysql_real_escape_string()不是万能解药:宽字节注入、多编码绕过、非字符串字段都可能失效 -
mysql_query已被 PHP 7.0+ 彻底移除,但存量系统里仍有调用,且逻辑漏洞照旧存在
真正安全的替代路径只有两条
不是“换函数就行”,而是必须改变数据进入 SQL 的方式:
- 用
PDO+prepare()+bindValue():类型明确、参数隔离、驱动层处理转义 - 用
mysqli+prepare()+bind_param():同样强制类型绑定,且支持多语句(需显式开启) - 绝对避免把
$_GET、$_POST、$_SERVER['PATH_INFO']等直接拼进 SQL 字符串 - 数值型参数务必先
(int)强转或filter_var($x, FILTER_VALIDATE_INT)校验,再参与拼接(仅限极简场景兜底,不推荐)
最关键的盲区是:很多人以为“用了 mysql_real_escape_string 就安全了”,但只要还是字符串拼接,就永远存在绕过可能。预处理语句不是可选项,是唯一被验证有效的防线。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











