注释符通过让数据库解析器跳过后续字符来破坏SQL原始逻辑结构,例如输入admin' --会使SELECT * FROM users WHERE username = 'admin' --' AND password = '$pass'中AND条件被丢弃;单引号+注释是最常用闭合组合,因能同时闭合引号并截断尾部;参数化查询可彻底防御,因其将用户输入作为纯数据绑定,不参与SQL语法解析。

注释符如何破坏SQL原始逻辑结构
注释不是“让代码不执行”,而是让数据库解析器主动跳过后续字符——这直接切断了原SQL语句的语法完整性。比如原始语句是 SELECT * FROM users WHERE username = '$user' AND password = '$pass',当用户输入 admin' --,拼接后变成:SELECT * FROM users WHERE username = 'admin' --' AND password = '$pass'。数据库在遇到 -- 后就停止解析,后面整个 AND password = ... 被丢弃,条件只剩恒真部分。
为什么单引号+注释是最常用闭合组合
绝大多数字符串型注入点都用单引号包裹参数,所以攻击者第一步必须先闭合前面的引号,否则语法错误直接报错,注入失败。而 ' -- 既能闭合引号,又能注释掉尾部,一步达成两个目标。双引号或反引号场景同理,只是闭合符号不同:
- MySQL 字符串常用
'或",对应闭合用' --或" -- - PostgreSQL 支持美元符号引用(
$1$...$1$),此时需匹配定界符,不能硬套-- - SQL Server 中
--和/* */都可用,但/* */可跨行,更隐蔽
注释失效的典型场景与绕过方式
现代WAF或框架常拦截 --、# 等明显注释符,但这不代表注释技巧失效,只是需要换形式:
-
;分号可终止当前语句,后面跟新语句(如admin'; DROP TABLE users--),但前提是数据库支持多语句执行(MySQL 默认关闭,PHPmysqli_multi_query才启用) -
/* comment */不被所有WAF识别,且在MySQL中可嵌套(/*!50000 SELECT user() */还能触发条件执行) - 布尔盲注中根本不用注释——靠
AND 1=1/AND 1=2控制逻辑分支,页面有差异即可推进
预编译为何能彻底废掉注释攻击
参数化查询(如 PreparedStatement 或 mysqli_prepare)把SQL结构和数据完全分离:数据库先编译语句模板,再把用户输入当纯值绑定进去。此时输入里的 ' -- 不会被当作语法成分,只当字符串字面量处理,连引号都闭合不了——自然没机会注释任何东西。
真正容易被忽略的是:哪怕用了ORM(如Django ORM、Sequelize),如果调用了原始SQL接口(raw()、query())并拼接变量,照样中招。注释攻击是否有效,只取决于“有没有字符串拼接”,跟用不用框架无关。

















