跳转到主内容
趣航编程网 - 趣学编程,启航技术之路!

为什么使用addslashes函数不能完全防御SQL注入_推荐改用预编译处理

addslashes不能防住所有SQL注入,根本原因在于它不感知SQL语法上下文和数据库字符集,对数字型参数完全无效,且易受宽字节注入绕过;预编译+参数绑定才是可靠解法。 addslashes 不能防住所有 SQL 注入,根本原因在于它不感知 SQL 语法上下文和数据库字符集 addslashes 对数字型参数完全无效 当 SQL 中的字段是数字类型(如
id = ?
),却用字符串拼接方式写成
"id = '$id'"
,
addslashes
就毫无意义。攻击者直接传
id=1 OR 1=1
,不会触发任何单引号,转义逻辑压根不生效。 典型场景:
$sql = "SELECT * FROM users WHERE id = $id";
—— 这里
$id
没有引号包裹,
addslashes
加的反斜杠反而可能破坏整数解析 正确做法:数字参数必须强制类型转换(如
(int)$id
)或统一走参数绑定 隐患点:很多老代码把所有输入“习惯性”过一遍
addslashes
,误以为一劳永逸 宽字节注入可绕过 addslashes 在 MySQL 使用
GBK
、
GB2312
等多字节编码时,
addslashes
的转义会被吃掉一个字节。例如输入
%df%27
(
%df
是 GBK 下的合法首字节),MySQL 会将
%df%5c
(即
%df\
)识别为一个汉字,导致后续的
%27
(单引号)逃逸出来。 防SQL注入的php类库 防SQL注入的php类库 下载 触发条件:PHP 连接未显式设置字符集(如
SET NAMES gbk
),且 MySQL 配置为
character_set_client=gbk
mysqli_real_escape_string
能规避此问题,因为它依赖实际连接的字符集做转义;但
addslashes
完全无视这点 现代 PHP 默认用
utf8mb4
,但遗留系统或中间件仍可能降级到 GBK 预编译 + 参数绑定才是可靠解法 预编译的本质是把 SQL 结构和数据分离传输:先发模板(如
SELECT * FROM users WHERE username = ?
),再单独发参数值。MySQL 在服务端解析时,参数永远作为“数据”处理,不会参与语法解析。 MySQLi 示例:
$stmt = $mysqli->prepare("SELECT * FROM users WHERE username = ?"); $stmt->bind_param("s", $_GET['username']); $stmt->execute();
PDO 示例:
$stmt = $pdo->prepare("SELECT * FROM users WHERE username = ?"); $stmt->execute([$_GET['username']]);
注意:
PDO::ATTR_EMULATE_PREPARES
必须设为
false
,否则 PDO 会在 PHP 层模拟拼接,退化为字符串替换 无法参数化的部分(如表名、ORDER BY 字段)必须用白名单校验,不能靠任何转义函数 真正容易被忽略的是:预编译只保值,不保结构。哪怕用了
prepare
,如果把用户输入拼进表名、字段名或
UNION SELECT
子句里,照样中招。防御边界必须划清楚——哪些能参数化,哪些只能白名单,这个判断比写几行转义代码难得多。

相关文章