真正能落地的SQL注入监控是抓特征指纹而非全量解析:重点检测参数值中异常符号组合(如' OR '1'='1)、上下文位置、编码变形(%27)、注释符(--、/*)、非业务参数名含子查询、整型参数含+/-/0x等语义违例,结合客户端IP、耗时、会话关联与行为基线区分真实攻击。

怎么从日志里快速揪出可疑的 SQL 注入片段
真正能落地的监控,不是靠“全量解析 SQL”,而是抓特征指纹。重点盯住那些在正常业务中几乎不会出现、但注入攻击里高频复现的符号组合和模式。
-
' OR '1'='1、1; DROP TABLE这类字符串不是靠正则硬匹配——它们容易误杀(比如用户昵称含单引号),而是结合上下文判断:是否出现在参数值位置 + 是否伴随异常长度或编码(如%27代替') - 优先检查
WHERE子句前后的空格/换行/注释符:比如id=1/*或id=1--%20,--和/*在非管理接口中极少合法出现 - 注意 URL 参数名本身异常:比如
?id=1 AND 1=1是典型试探,但?sort=id ASC, (SELECT 1)更危险——这种嵌套子查询在排序参数里本不该存在
MySQL / PostgreSQL 日志里哪些字段最值得实时提取
数据库原生日志(如 MySQL 的 general_log 或 PostgreSQL 的 log_statement = 'all')信息冗余大,但关键字段就三个:执行语句原文、客户端 IP、执行耗时。别试图解析 AST,先做轻量级文本特征扫描。
- 必须开启
log_slow_admin_statements(MySQL)或log_min_duration_statement = 0(PG),否则 DDL 类注入(如DROP)可能被跳过 - 避免直接解析
information_schema查询:正常运维也会查它,但SELECT * FROM information_schema.tables WHERE table_name LIKE '%user%'加了模糊匹配 + 非业务表名,就是高危信号 - 对
UNION SELECT要分场景:报表导出功能里允许是合理的,但在登录接口的username参数后拼出UNION SELECT password FROM users就得立刻告警
为什么 WAF 规则总漏掉变形注入(比如宽字节、注释绕过)
WAF 基于规则匹配,而攻击者只用改几个字符就能绕过。真正有效的指纹不是“匹配字符串”,而是“违背语义约束”。比如一个整型 ID 参数,值里出现 +、-、/*、0x 开头的十六进制,基本可判异常。
- 宽字节注入(如
%df%27)本质是编码不一致:应用用gbk解码,MySQL 却按utf8处理。监控时应比对请求原始 bytes 和数据库实际接收的字符流,发现%df后紧跟%27且未被正确转义,即触发 - 注释符绕过常见于
ORDER BY后:正常排序参数是数字,但order=1,1/**/UNION/**/SELECT里/**/出现在非注释上下文,就是强指纹 - 别依赖单一 WAF:把 Nginx 的
$request_uri和应用层query_string对比,如果后者被框架自动 decode 过而前者没动,中间的编码差就是绕过入口
用什么工具做实时指纹比对才不至于拖垮数据库
不要让数据库自己跑正则或 JSON_EXTRACT。指纹检测必须前置到接入层或独立采集进程,数据库只负责吐原始日志。
- 推荐用
filebeat+dissect过滤器提取 SQL 字段,再用grok匹配高危模式(如UNION.*SELECT.*FROM),全程不触碰数据库连接 - 如果用 Python 做二次分析,别用
re.search扫全文本,而是先用str.find()定位SELECT、UNION、EXEC等关键词,再局部检查前后 20 字符内是否有非法符号 - 注意 PostgreSQL 的
log_line_prefix必须包含%m(时间)和%u(用户),否则无法关联同一会话的多条语句,漏掉分步注入(如先SET再EXECUTE)
最麻烦的不是识别,而是区分“测试行为”和“真实攻击”:内部渗透测试、开发调试、甚至某些 BI 工具生成的动态 SQL,都会长得像注入。得靠白名单+行为基线(比如某个接口历史 99.9% 的参数长度 WHERE 条件,就得人工确认)










