真正有效的sql注入防御需从数据库协议层实时监控并行为建模,而非依赖waf或输入过滤;mysql 8.0+需正确配置audit_log插件及日志路径权限,postgresql启用pgaudit须注意超级用户权限、参数配置与pgbouncer溯源陷阱,且应使用官方解析工具处理审计日志,关注异常行为特征而非单条语句,同时防范日志明文带来的安全风险。

SQL注入防御不能只靠WAF或输入过滤
单靠应用层校验或中间件拦截,UNION SELECT、sleep(5)、extractvalue() 这类变体依然能绕过。真正有效的实时监控必须从数据库协议层捕获原始查询,再结合行为建模判断异常——不是看“有没有SELECT”,而是看“为什么这个用户突然查了information_schema.tables且没走业务接口”。
MySQL 8.0+ 开启 audit log 的实操要点
官方audit_log插件默认不启用,且日志格式不直接包含客户端IP和执行耗时,容易漏掉关键上下文。
- 先确认插件已加载:
SHOW PLUGINS;查看audit_log状态,未激活则运行INSTALL PLUGIN audit_log SONAME 'audit_log.so'; - 关键配置写进
my.cnf,不是动态 SET:audit_log_policy=ALL(否则只记失败)、audit_log_format=NEW(旧格式缺绑定参数)、audit_log_connection_policy=ON(记录连接来源) - 日志默认输出到
/var/lib/mysql/audit.log,但该文件权限为 root:root,应用监控进程若非 root 无法读取——建议用audit_log_file指向可读路径,并配audit_log_rotate_on_size防止撑爆磁盘
PostgreSQL 启用 pgAudit 时的权限陷阱
pgaudit 不是开个扩展就完事,它依赖会话级角色权限,且审计粒度受 pg_hba.conf 认证方式影响。
- 必须用超级用户执行:
CREATE EXTENSION pgaudit;,普通用户即使有CREATEROLE也不行 - 审计生效需设两个参数:
shared_preload_libraries = 'pgaudit'(重启生效) +pgaudit.log = 'read, write, ddl, role, misc'(热加载) - 如果客户端通过 pgbouncer 连接,
client_addr会固定为 pgbouncer IP——得在pgbouncer.ini中配ignore_startup_parameters = application_name,并在应用里传真实标识,否则溯源失效
实时解析审计日志时别硬解 JSON 或正则
MySQL 的 audit_log_format=NEW 输出是 JSON,PostgreSQL 的 pgaudit 默认是 CSV,但字段顺序、转义规则、嵌套层级都可能随版本变化。
- 优先用官方工具:MySQL 推荐
mysql-audit-log-parser(Oracle 官方维护),PostgreSQL 推荐pgauditlogtojson,它们处理\x00、多行值、空字段等边界情况更稳 - 避免用
grep -E "SELECT.*FROM.*information_schema"做告警——攻击者改用SELECT/**/1/**/FROM/**/inf...就绕过 - 真正要盯的是高频低价值查询组合:比如 1 分钟内出现 >3 次
pg_sleep+current_database(),这种行为特征比单条语句更可靠
审计日志本身是明文,传输和存储环节没加密,意味着日志收集服务一旦被攻破,等于把所有 SQL 流量白送出去。这点常被忽略。










