连接池本身不防sql注入,真正防护靠preparedstatement;但cacheprepstmts与useserverprepstmts必须成对启用才能实现服务端预编译,否则客户端模拟仍可被绕过。

连接池本身不防SQL注入,但配置不当会削弱参数化查询的实际防护效果——比如让预处理语句失效、复用残留语句、暴露高权限上下文。
cachePrepStmts 和 useServerPrepStmts 必须成对启用
只设 cachePrepStmts=true 而不设 useServerPrepStmts=true,MySQL JDBC 驱动会在客户端模拟预编译,攻击者仍可能通过特定 payload(如含注释或换行的输入)绕过绑定逻辑。服务端预编译才是真正的隔离:SQL 模板由 MySQL 服务端解析一次,后续只传参数值。
-
cachePrepStmts=true开启客户端缓存,但只是“记住了 PreparedStatement 对象”,不是安全机制 -
useServerPrepStmts=true强制走 MySQL 的PREPARE协议,这是防绕过的底线 - 二者缺一,
prepStmtCacheSize再大也无意义;实测中未启用后者时,' OR 1=1 /*类输入仍可触发条件恒真
连接池账号权限必须按模块最小化
即使所有 SQL 都用了 PreparedStatement,如果连接池用的是 root 或带 FILE 权限的账号,攻击者一旦控制应用进程(例如通过反序列化漏洞),就能直接执行 SELECT ... INTO OUTFILE 或读取系统表,完全绕过业务层防护。
- Web 前端服务只应有
SELECT, INSERT, UPDATE权限,且限定在具体表(如myapp.users),禁用DELETE和跨库访问 - 后台任务账号若需清理数据,优先用存储过程封装逻辑,而非开放
DELETE权限 - 绝对禁用
GRANT OPTION、SUPER、PROCESS—— 这些权限在连接池配置里哪怕只出现一次,就等于留了后门
禁用危险连接池初始化行为
很多连接池支持初始化 SQL(如 HikariCP 的 connection-init-sql),若这里写了 SET sql_mode='' 或 SET autocommit=0 以外的语句,可能在每次连接建立时重置数据库安全策略,甚至触发权限提升路径。
- 默认关闭所有初始化 SQL;除非明确需要且已审计其副作用,否则不要配
- 检查是否启用了
allowMultiQueries=true(MySQL JDBC)—— 它会让分号分隔的多语句逃逸参数化保护,例如userInput="admin'; DROP TABLE users; --" - 避免
autoReconnect=true:重连时若凭证泄露,会扩大攻击面;现代连接池更推荐用validationQuery+isValid()主动探测连接有效性
真正起作用的从来不是连接池的某个开关,而是它如何配合 PreparedStatement 的生命周期管理与权限边界收敛。最容易被忽略的一点是:连接池复用连接时,不会自动清理上一个请求遗留的会话级设置(如临时表、用户变量、SQL mode),这些状态残留可能间接干扰预处理语句的参数绑定行为。











