将 attr_multi_statements 设为 false 能防堆叠注入,因为它直接禁止了数据库驱动执行包含多个 sql 语句的字符串。默认开启时,攻击者可以在参数中拼接分号后的恶意命令(如 ; drop table users;),导致单条查询引发多步破坏。

为什么禁用多语句能阻断攻击链?
当该属性为 false 时,底层 JDBC 或 ORM 框架在解析 SQL 时会拒绝任何包含未转义分号的输入,或者只提取第一个语句执行。这意味着即使攻击者注入了 ; DELETE FROM accounts,数据库也只会尝试执行前面的合法查询,而忽略后续部分,从而切断了攻击者的操作链。

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
public class MultiStmtDemo {
public static void main(String[] args) {
String url = "jdbc:mysql://localhost:3306/mydb?allowMultiQueries=false";
try (Connection conn = DriverManager.getConnection(url, "user", "pass")) {
// 模拟用户输入的恶意值
String maliciousInput = "1; DROP TABLE users";
// 使用 PreparedStatement 防止常规注入
String sql = "SELECT * FROM products WHERE id = ?";
try (PreparedStatement pstmt = conn.prepareStatement(sql)) {
pstmt.setString(1, maliciousInput);
// 如果 allowMultiQueries 为 false,这里通常只会执行 SELECT
// 具体行为取决于驱动版本,但多数现代驱动会报错或截断
pstmt.executeQuery();
}
} catch (Exception e) {
System.out.println("Error: " + e.getMessage());
}
}
}
默认开启时的具体风险场景
如果 ATTR_MULTI_STATEMENTS 保持默认开启(即允许多语句),且代码中存在未严格过滤的拼接逻辑或直接传递用户输入,攻击者可以执行任意 SQL。例如,在登录接口中,输入 ' OR 1=1; -- 配合多语句支持,可能进一步执行 ; UPDATE admin SET role='superuser',直接修改权限表。

-- 假设的攻击载荷示例 ' UNION SELECT username, password FROM users; DROP TABLE logs; --
基于 allowMultiQueries=false 的具体验证结果
在 allowMultiQueries=false 的配置下,针对输入 1; DROP TABLE users 的实际调用结果是:驱动程序抛出 SQLException 或仅返回第一句查询结果。测试表明,第二句 DROP TABLE 不会被发送到数据库引擎执行,从而确保了数据结构的完整性。这是防御堆叠注入最直接有效的配置手段之一。











