必须接入数据库审计日志才能实时发现SQL注入,因仅此处记录真实执行语句,可识别OR 1=1、UNION SELECT等载荷;Web日志仅存URL编码参数,无法还原SQL逻辑且漏报盲注、报错注入。

要实时发现针对Web服务的SQL注入尝试,核心不是看Web访问日志,而是必须接入数据库层的审计日志——因为只有这里记录的是真实执行的SQL语句,能暴露OR 1=1、UNION SELECT、--注释、/* */包裹的恶意载荷等关键痕迹。
必须启用数据库原生审计,而非依赖Web日志
Web服务器日志(如Nginx access.log)只保存URL编码后的参数,例如 /user?id=1%27%20OR%201%3D1。这类字符串无法还原成可判断的SQL逻辑,直接匹配误报率极高,且无法识别盲注、报错注入等无显式响应的攻击。
- MySQL 8.0+ 推荐启用
log_statement = 'ALL'或安装官方审计插件(如 mysql-audit),避免使用已弃用的 general_log(性能差、CSV表无索引、仅对新连接生效) - PostgreSQL 必须安装并配置
pg_audit扩展,关键设置包括:pgaudit.log = 'read, write'、pgaudit.log_catalog = off(防干扰)、pgaudit.log_parameter = on(确保参数值可见) - SQL Server 应启用 SERVER AUDIT 并捕获
BATCH STARTED和EXECUTE事件,特别关注含分号的堆叠语句,如SELECT *; DROP TABLE logs;
用结构化方式提取SQL文本,别硬写正则
审计日志格式各异:MySQL 审计日志是 JSON,pg_audit 是带引号的纯文本,Oracle 又是另一套。在 Logstash 或类似管道中,优先用解析型插件提取结构字段,再补充轻量匹配。
- MySQL JSON 日志示例:
{"sql_text":"SELECT * FROM users WHERE id = 1 OR 1=1"}→ 直接用json插件取sql_text字段 - pg_audit 文本日志:
AUDIT: ... "SELECT * FROM users WHERE name = 'admin''; DROP TABLE users; -- '"→ 用dissect提取双引号内内容,比 grok 更稳定、更少漏掉换行或注释包裹的 payload - 避免自定义
%{SQL}这类不可维护的 grok 模式;也别试图用单条正则覆盖所有数据库语法变体
聚焦高置信度注入特征,做实时规则过滤
不建议泛泛扫描“union”“select”等通用词——正常业务查询也会高频出现。应组合语法特征与上下文异常,提升准确率。
- 检测布尔/盲注典型模式:
OR\s+1\s*=\s*1、AND\s+\(\s*SELECT\s+\d+\s*\)、AND\s+\(SELECT.*?FROM.*?\)\s*>\s*0 - 识别报错注入函数:
UPDATEXML\(|EXTRACTVALUE\(|FLOOR\(RAND\(0\)(注意括号和空格变体) - 标记危险操作组合:含
UNION ALL SELECT且目标表非业务表(如information_schema、mysql.user);含EXECUTE IMMEDIATE或XP_CMDSHELL等系统调用 - 关注异常参数值:WHERE 条件中出现连续单引号
''、结尾带--或/*、含;--分号注释组合
配合 Kibana 做动态告警与上下文钻取
把清洗后的 SQL 文本、用户IP、数据库账号、时间戳、影响行数等字段写入 Elasticsearch,就能在 Kibana 中构建实时看板。
- 设置阈值告警:例如 5 分钟内同一 client_ip 触发 3 条含
OR 1=1的查询,自动触发企业微信/邮件通知 - 关联分析:点击某条可疑语句,下钻查看该账号最近 1 小时所有操作,是否紧跟着查
sys.tables或pg_roles——这是权限探测的典型前兆 - 排除白名单:对运维脚本、ETL任务使用的固定账号加 filter,减少干扰;但需定期复核,防止被攻击者盗用

















