应通过sql模板下参数引发的执行计划抖动识别注入,而非关键词匹配;关注query_time:max/avg>10、rows_sent标准差远超均值等行为异常,并结合explain对比及连接池阻塞分析确认。

不能靠关键词匹配来判断,得看同一SQL模板下不同参数引发的执行行为抖动——这才是注入扫描最真实的痕迹。
为什么直接 grep UNION SELECT 会漏掉绝大多数攻击
攻击者早就不写裸关键字了:UNION%20SELECT、unIoN/**/selECT、%75%6e%69%6f%6e%20%73%65%6c%65%63%74 都不会被 LIKE '%union%select%' 捕获;general_log 在生产环境基本不开,开了也撑不住,查起来像刮痧。真正该盯的是行为异常:比如一个本该走 idx_user_id 的查询,在传入 ' OR 1=1 后突然变成 type: ALL,执行计划里 rows_examined 从 10 跳到 100 万。
用 pt-query-digest 聚合慢日志时必须关注的两个比值
别只看单条 SQL 多慢,要按 SQL 模板(fingerprint)聚合后看波动:
-
Query_time:max / Query_time:avg > 10:说明同样结构的语句,某些参数让它慢了十倍以上 -
Rows_sent 标准差远大于均值:比如均值是 1 行,标准差却达 5000,意味着有的请求返回 1 行,有的返回上万行——典型爆库或扫表行为 - 必须设
long_query_time = 0.1:否则SLEEP(5)类盲注试探直接被过滤,根本进不了慢日志
EXPLAIN 对比才是确认注入路径的关键动作
拿到可疑 SQL 模板后,拿两个典型参数分别跑 EXPLAIN:
- 正常参数(如
user_id = 123)→type: ref,key: idx_user_id - 可疑参数(如
user_id = 123 OR 1=1)→type: ALL,key: NULL,rows_examined爆增 - 注意 MySQL 5.7+ 直方图或
optimizer_switch变更可能造成执行计划突变,但如果是同一批参数反复触发突变,基本可锁定为注入试探
别忽略连接池阻塞带来的毛刺传导
一条注入语句卡住连接池,后续所有请求都会排队等连接,导致你看到的“慢接口”其实是被前面那条恶意 SQL 拖垮的——所以发现某类请求集中变慢时,先查 information_schema.PROCESSLIST 里有没有 TIME > 60 且 STATE = 'Sending data' 的长连,再顺藤摸瓜找它的 SQL。











