WAF规则怎么写才有效?

wen 开源项目 64

本文目录导读:

WAF规则怎么写才有效?

  1. 核心原则:先建白名单,后封黑名单
  2. 第一部分:如何写好一条规则?(黄金四要素)
  3. 第二部分:实战规则写法(从基础到高级)
  4. 第三部分:常见场景的“有效”规则速查表
  5. 第四部分:写完后,如何验证有效性?
  6. 总结:一条“有效”的WAF规则长什么样?

写一份有效的WAF(Web应用防火墙)规则,核心不在于“写得多”,而在于“精准”“低误报”“适应业务”,以下是编写有效WAF规则的实战原则和示例。

核心原则:先建白名单,后封黑名单

  • 无效的WAF:一上来就写“禁止SQL注入”、“禁止XSS”这种宽泛的规则,结果把正常用户写的“文章标题带单引号”给拦截了。
  • 有效的WAF:先梳理业务,明确哪些是正常流量,针对非正常部分做精确限制。

第一部分:如何写好一条规则?(黄金四要素)

一条有效的规则通常包含以下四个维度的组合:

  1. 源(Source): IP地址、国家、ASN、请求来源。
  2. 请求特征(Request): URI(访问路径)、Header(头部)、Body(请求体)、HTTP方法(GET/POST/PUT)。
  3. 匹配模式(Pattern): 正则表达式、字符串包含、长度限制、频率统计。
  4. 动作(Action): 监控(Log)、放行(Allow)、拦截(Block)、挑战(Challenge/JS验证)、限速(Rate Limit)。

第二部分:实战规则写法(从基础到高级)

语法级:精确匹配 > 正则 > 通用规则

  • 错误写法if body contains "select" then block (会把“select your option”这种正常页面也封掉)
  • 有效写法if body matches “/[\b(SELECT|UPDATE|DELETE)\b]\s+\b(FROM|SET|INTO)\b/i” then block (要求必须有SQL关键字组合)

防护级:建立多道防线

路径级白名单(最有效)

  • 规则示例/api/login 路径只允许 application/json 的POST请求,其余统统拦截。
  • 写法if request.method == "POST" and request.uri starts with "/api/user/" and request.content-type != "application/json" then block

参数级强校验

  • 规则示例/user?id=abc 应该被拦截,因为id参数应该是数字。
  • 写法if request.uri matches "^/user\?id=" and request.args.id matches "^[a-zA-Z]+$" then block

动态规则(机器学习/防护)

  • 原理:不写死规则,而是建立一个“正常行为基线”。
  • 示例:某个API在3分钟内正常请求是10次,突然达到1000次,触发限速。

绕过防护:必须考虑的4种情况

避免被绕过,是有效规则的关键:

  • 大小写混淆SeLeCt。 → 对策:规则统一 tolower() 处理。
  • 双重编码%25%32%37 (URL编码后的单引号)。 → 对策:先做一次 urldecode 再匹配。
  • 注释拆解SEL/**/ECT 。 → 对策:正则中匹配 \W*\b 跳过注释符号。
  • 协议模糊: 在Multipart上传的body里藏payload。 → 对策:确保WAF能解析 multipart/form-data

第三部分:常见场景的“有效”规则速查表

场景 无效/危险的写法 有效/精准的写法
XSS攻击 if body contains "<script>" then block if body matches “/<(script|img|link|iframe)[\s]+[^>]*?(onerror|onload|onclick)=/i” then challenge (增加JS验证)
SQL注入 if body contains “'” then block if request.uri matches “/search?” and args.keywords matches “/\b(SELECT|UNION|INSERT)\b/i” then block
CC攻击 if rule rate > 100 then block if client.ip rate per 60s for uri: /api/register > 20 then challenge (对敏感路口单独限速)
扫描器 if user-agent contains “sqlmap” then block if user-agent not in [“Mozilla/5.0...”, “curl/7...”, “PostmanRuntime/...”] request.path matches “/(admin|phpinfo|\.env)” then challenge

第四部分:写完后,如何验证有效性?

规则的失效往往发生在“上线之后”,建议按以下步骤验证:

  1. 部署模式:先监控,后拦截

    • 新规则刚开始设为 Log 模式(只记录不拦截),观察1-2天,看是否有正常请求被误报。
    • 指标:误报率 < 0.01% 才算合格。
  2. 压力测试

    • 使用 OWASP ZAPSQLMap(加上 --random-agent--tamper=space2comment 等绕过参数)测试。
    • 如果被绕过,说明规则不够“严格”,需要增加更多特征(如:请求时间、参数长度、Cookie值)。
  3. 持续迭代

    • 无效规则的特征:每天产生大量误报(正常用户投诉)或者完全0命中(可能被绕过了)。
    • 有效规则的特征:每周命中量稳定,误报极少,且能捕获利用 0day 漏洞的请求。

一条“有效”的WAF规则长什么样?

规则名称:精确的、针对特定API的参数校验规则
请求条件http.request.uri eq "/api/v1/order"
匹配条件http.request.body.args.total_price not matches "^[0-9\.]+$"
防护行为block (返回403)
附加策略:同时对该端点的同IP请求限速 每分钟30次
模式监控运行72小时无误报后,正式启用

最后记住:WAF是药,不是饭,最好的防护是代码层没有漏洞,WAF只是兜底。 如果业务代码本身有高危风险(如SQL拼接),再好的WAF规则也只能防住90%,总有漏网之鱼。

抱歉,评论功能暂时关闭!