禁用多语句执行能从根本上阻断堆叠注入,因其依赖mysqli_multi_query或PDO::MYSQL_ATTR_MULTI_STATEMENTS等驱动层支持,而WAF过滤分号可被编码绕过,唯有在连接初始化时禁用才彻底消除执行基础。
普通 SQL 注入(如 UNION 或盲注)通常只能读取数据,而堆叠查询允许在一次请求中执行多条语句,比如 '; DROP TABLE users; -- 或 '; INSERT INTO admins VALUES ('hacker', 'pwd'); --。只要后端用了 mysqli_multi_query()、PDO::MYSQL_ATTR_MULTI_STATEMENTS = true 这类支持多语句的驱动配置,数据库就会顺序执行——先查,再删,再插,完全不受应用层逻辑约束。
MySQL 服务本身默认只接受单条语句,真正打开堆叠大门的是客户端驱动的行为:
mysqli_query() 遇到分号直接报错:MySQLi SQL syntax error
mysqli_multi_query() 是唯一默认允许堆叠的函数,且不校验第二条语句合法性PDO::MYSQL_ATTR_MULTI_STATEMENTS => true,风险立刻回归很多旧项目初始化 PDO 时没关这个 flag,或直接用 mysqli_multi_query() 做批量操作,结果把注入入口从“只读”升级成“可写可删”。
分号(;)看似容易拦截,但攻击者有太多绕过方式:
%3B 替代 ;
;/**/DROP/**/TABLE
真正有效的防线是连接建立那一刻就掐断能力——不是过滤输入,而是让驱动根本不具备执行多语句的权限。
禁用 mysqli_multi_query() 或关闭 PDO::MYSQL_ATTR_MULTI_STATEMENTS 后,部分旧逻辑会直接崩溃,而不是静默降级:
Cannot execute queries while other unbuffered queries are active
这类调用往往不在主业务链路,排查时容易被当成环境问题跳过,实际却是堆叠禁用后的必然表现。