waf规则中request.body为空因框架未主动解析,需显式调用get_data()或body()且注意读取次数;正则检测应匹配结构特征、url解码后匹配、避免回溯爆炸;选flask中间件或uwsgi钩子取决于校验深度;日志应在after_request或dispatch中记录真实status_code。

WAF 规则里 request.body 为什么总为空?
Python Web 框架(如 Flask、FastAPI)默认不主动解析 request.body 为字典或对象,WAF 中直接读取原始字节流时,若没提前调用 request.get_data() 或类似方法,request.body 可能返回空 bytes 或引发重复读取错误。
- Flask 中必须显式调用
request.get_data(cache=True)才能多次安全读取;不加cache=True会导致后续视图函数拿不到 body - FastAPI 的
Request对象需用await request.body(),且只能 await 一次;WAF 中若提前 await 过,视图里再 await 就会卡住或报错 - Content-Type 是
application/json时,别直接 parse raw body——框架已解析好在request.json,但 WAF 层通常拿不到,得自己json.loads(request.get_data()) - multipart/form-data 场景下,原始 body 含边界字符串,正则匹配规则极易误判;建议先用
cgi.parse_multipart或轻量解析器提取字段再校验
用 re.search() 写 SQL 注入规则,为什么漏报率高?
单纯靠正则匹配 SELECT、UNION、; 等关键词,既容易被编码绕过(如 %20UNION%20),又会产生大量误报(比如用户昵称含 union)。
- 优先匹配“结构特征”而非关键词:例如
re.search(r"(?i)(SELECT|INSERT|UPDATE)s+.*?FROMs+.*?WHEREs+.*?=s*['"].*?[^\]['"]", body),比单独找UNION更可靠 - 对 URL 参数和 Cookie 值做 URL 解码后再匹配,否则
%3B(分号)永远躲得过检测 - 避免在正则中使用
.*开头——回溯爆炸风险高,改用[^'";]*等有界表达式 - 注意 Python 正则默认不支持 Unicode 字符类,中文注释或宽字节 payload(如
%A1%A1)需加re.UNICODE标志
Flask 中间件 vs. uWSGI 请求钩子,哪个更适合插 WAF 规则?
中间件能拿到完整请求上下文,但会拖慢所有请求;uWSGI 钩子(如 request-hook)在更底层运行,性能好但看不到 Python 层解析后的数据(比如 request.args)。
- 需要检查 JSON 字段值、Header 语义、登录态 token 有效性 → 选 Flask 中间件,用
@app.before_request或自定义Middleware类 - 只做粗粒度拦截(如黑名单 IP、异常 User-Agent、超大 Content-Length)→ 用 uWSGI 的
--request-hook或 Nginx 的limit_req更轻量 - 中间件里别调用
abort(403),它会触发 Flask 异常处理链,增加开销;直接return Response(..., status=403) - 如果用了 Gunicorn,没有 uWSGI 那套钩子,就老实用中间件 +
gunicorn --preload减少模块重复加载
response.status_code 被篡改后,WAF 日志怎么同步记录?
很多 WAF 规则在请求阶段就 return 了响应,但实际状态码可能被后续中间件或视图覆盖(比如 auth 中间件把 200 改成 401),导致日志里记的和客户端收到的不一致。
立即学习“Python免费学习笔记(深入)”;
- 不要在
before_request里记最终状态码;改用after_request回调,此时response.status_code已确定 - 如果用了异步视图(FastAPI),
after_request不生效,得用Starlette Middleware的dispatch方法包裹整个生命周期 - 记录日志时,把原始请求路径、匹配到的规则 ID、响应耗时、真实
response.status_code一起写入,别只存“拦截成功”这种模糊字段 - 注意:某些 WAF 规则会设置
response.headers['X-WAF-Action'] = 'blocked',但这个 header 可能被下游代理删掉,不能当唯一依据










