字符串拼接的PDO SQL查询能否抵御注入?求解
字符串拼接SQL加了分号依然不安全,预处理才是正道
兄弟,先给你拍板:这种用字符串拼接生成SQL的写法绝对不安全,哪怕你特意给语句加上分号结尾,也挡不住SQL注入攻击,别抱有任何侥幸心理。
举个最直白的例子,假设你的$id变量被攻击者传入了这样的值:'1; DROP TABLE my_table;--'
那你拼接后的SQL就会变成:
SELECT * FROM `my_table` WHERE `pk_id` = '1; DROP TABLE my_table;--';
数据库执行这条语句的时候,会先跑完前面的SELECT查询,接着执行后面的DROP TABLE——直接把你的表删了!后面的--是SQL注释符,会把最后那个多余的分号注释掉,让整个恶意语句合法执行。
你以为加个分号就能截断恶意代码?太天真了,攻击者有一百种方式绕过这种“手动防护”。
为什么预处理语句能确保安全?核心在于参数化查询:
- 预处理是先把SQL的结构(比如
SELECT * FROM my_table WHERE pk_id = ?)发给数据库编译,数据库会先确定这条语句的执行逻辑; - 之后再把
$id作为纯参数传入,数据库会把参数当成普通数据处理,不会把参数里的任何特殊字符(分号、引号、注释符)解析成SQL指令。
哪怕攻击者传入再恶意的参数,也只会被当成pk_id字段的查询值,不会触发额外的SQL操作。
顺便提一句:别想着自己手动过滤参数来替代预处理,手动过滤很容易有遗漏——比如编码转换、特殊字符的变种、不同数据库的语法差异,这些都可能让你的过滤失效。预处理是业界公认的、最可靠的防SQL注入方案。
最后给你改写成安全的预处理写法:
$pdo = new PDO($dsn, $usr, $pass); // 用占位符?定义参数位置 $stmt = $pdo->prepare('SELECT * FROM `my_table` WHERE `pk_id` = ?;'); // 传入参数数组执行 $stmt->execute([$id]); // 获取结果 $res = $stmt->fetchAll();
内容的提问来源于stack exchange,提问作者treyBake
相关产品推荐
相关产品推荐

