真正起作用的是SQL语句结构异常而非关键词匹配;需先协议解析、参数切分并还原编码,再用sqlparse提取语法树特征(如嵌套深度、子查询数、关键字位置),并实时监控语法特征漂移。

SQL注入变种太多,关键词匹配根本拦不住
关键词匹配(比如查 UNION、SELECT、--)在真实流量里漏报率极高。攻击者把 UNION SELECT 拆成 UNI/**/ON SEL/**/ECT,或用宽字节 %A1%94 绕过正则,模型直接失效。真正起作用的不是“有没有这个词”,而是“这句话像不像人写的SQL”——得看结构。
别直接喂原始字符串,先做协议解析和参数切分
HTTP请求里的恶意载荷从来不在整条URL里,而在某个 value 字段中。直接把 GET /search?q=1%27%20OR%201%3D1-- 当作一条文本训练,模型学的是URL编码风格,不是SQL逻辑。
- 用
urllib.parse.parse_qs()或requests.utils.requote_uri()先还原编码,再按key=value拆开 - 每个
value单独走后续流程,丢掉明显白名单字段(如匹配^\d{11}$的手机号、^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}$的邮箱) - 保留原始
key名作为上下文特征(例如id字段突然出现;比comment字段出现更可疑)
用 sqlparse 提取语法树异常,不是只看能否解析成功
sqlparse.parse() 返回的不是布尔值,而是一棵树。重点不是“能不能 parse”,而是“parse 出来的东西反不反常”。
- 记录
parse_error标志,但别直接当标签——很多合法ORM生成语句也会报错(如SELECT * FROM users WHERE id IN (?)) - 统计括号嵌套深度:正常查询通常 ≤ 2 层,盲注常用
(SELECT (SELECT (SELECT ...)))达到 5+ 层 - 子查询数量:单层
SELECT是常态,SELECT ... (SELECT ... (SELECT ...))是强信号 - 关键字位置偏移:比如
FROM出现在第 3 个 token 而不是前 5 个,说明前面塞了大量干扰字符
模型上线后最常崩的点:没监控语法特征漂移
业务一改接口格式,语法特征分布就偏移。比如原来 id=123 突然变成 id={"type":"user","val":123},sqlparse 对 JSON 字符串直接报错,所有 parse_error=1 的样本暴增,模型误判率飙升。
必须加实时监控:parse_error 率周同比变化 >15%、括号深度中位数突降、子查询数量 95 分位骤升——这些比准确率下降更早暴露问题。特征漂移不处理,模型再高 AUC 也撑不过两周。











