尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

WAF规则编写与防护策略定制实战:从规则原理到安全体系搭建

WAF规则编写与防护策略定制实战:从规则原理到安全体系搭建 做安全的朋友应该都有过这种经历业务上线前扫了一遍漏洞发现一堆SQL注入和高危接口上线后又被人用脚本打了一晚上日志里全是奇奇怪怪的请求。这时候最头疼的不是漏洞本身而是怎么把风险挡在外面同时又不影响正常业务。我这些年折腾过不少WAF从自写规则到开源方案再到云服务踩了无数坑也攒了一些真正能落地的经验。这篇就把WAF规则编写、防护策略定制、安全防御体系搭建这件事从设计思路到实际操作完整讲一遍特别适合正在搭防护、被误报搞到头大、或者刚上手WAF的运维和开发同学。先交代一下背景我常用的是开源WAF和云WAF组合比如长亭雷池社区版、ModSecurity以及AWS WAF这类托管服务。不同场景下选型逻辑完全不一样但核心思路共通——规则要能精准拦截策略要能贴合业务体系要能兜底。接下来我会从一个真实项目的角度把从零搭建防护的全过程拆开讲包括规则怎么写、策略怎么定、怎么用Docker Compose一键部署一套能跑的WAF以及遇到WAF绕过时怎么反制。全文以实操为主尽量不废话。1. 内容整体设计与思路拆解1.1 先想清楚WAF到底要防什么很多人一上来就装个WAF、套一堆默认规则就觉得高枕无忧了。但WAF不是银弹它的核心价值是拦截那些特征明显的攻击流量比如SQL注入、XSS、命令注入、路径穿越、恶意文件上传以及一定规模的CC攻击。你得先盘点业务里有哪些入口每个入口可能遇到什么攻击才能决定规则怎么配。我从一个典型Web应用来说它有用户登录、商品查询、下单支付、后台管理这几个模块。登录接口要防暴力破解和撞库商品查询大概率存在SQL注入风险很多团队喜欢把查询条件拼进SQL下单支付要考虑重放和参数篡改后台管理则要防未授权访问和命令注入。针对这些场景WAF规则不能一套打天下得像给不同房间配不同钥匙一样区分对待。1.2 WAF选型开源、商业还是云WAF选型这事没有绝对答案但有几个判断维度成本、可控性、接入方式、规则生态。如果你公司有专门的运维安全团队Self-hosted的开源方案ModSecurity、雷池更适合因为规则可以深度定制数据不出内网。如果业务量不大、又想要开箱即用云WAFAWS WAF、阿里云WAF更省心但要注意规则能力和限制。我自己用得比较多的是长亭雷池社区版原因是它提供了可视化的规则配置和站点防护而且社区活跃规则更新及时。另外雷池基于Nginx性能还不错用Docker Compose部署十分方便后面会专门给出一套保姆级教程。AWS WAF则是当业务上云后的补充它的规则可以跟ALB、CloudFront、API Gateway联动适合分布式防护。但要清楚云WAF免费版规则深度一般真要防复杂绕过还是要自己写规则。1.3 部署模式反代、透明桥接还是DNS接入WAF怎么接入流量决定了它能“看到”什么。最常见的是反向代理模式WAF作为一个中间层所有请求先经过它再转发到源站。这种方式对协议解析最充分规则也最好写缺点是源站IP会暴露如果WAF挂掉会影响整个业务。透明桥接模式是在链路上串个设备不改变网络拓扑但部署复杂。DNS接入则把域名解析到WAF配置简单但对非HTTP协议比如WebSocket支持较差。从防护效果看我强烈建议优先反向代理模式。它有一个隐藏优势可以隐藏源站攻击者直接扫源站IP会扑空。而且你在WAF上做限流、封禁、改写请求头都是顺理成章的事。雷池和Nginx类WAF默认就是反代模式配置起来也不复杂。如果你的业务有多个域名、多个源站反代模式能统一管理入口减少漏配。2. 规则编写从原理到实战2.1 规则引擎的底层逻辑匹配什么、怎么匹配、匹配后做什么WAF规则的本质就是“模式匹配动作”。模式匹配的目标是请求中的多个字段URI、查询参数、POST body、Headers、Cookie甚至响应体。每个字段经过解码、归一化后再跟规则库里的特征比对。比如一条SQL注入规则它会在所有参数值里寻找union select、sleep(这类特征一旦命中就执行动作。常见的动作有三种拦截阻断请求、放行允许通过、记录仅告警。这里的关键是规则不要一上来就拦建议先设成“观察模式”跑一段时间看误报率。我见过很多事故都是运维拍脑袋加了条规则结果把正常商品搜索词比如带“select”这个词全拦了业务直接报障。所以规则要分步上线先记录、再告警、最后拦截。另外规则引擎的匹配顺序也重要。多数WAF有规则优先级比如CRS规则集按严重级别排序你要把业务自定义规则放在高优先级位置否则可能被全局拦截规则抢先处理了。在ModSecurity里是SecRuleUpdateTargetById调整在雷池里则是界面拖拽排序非常直观。2.2 SQL注入过滤规则为什么不能只挡“mysql关键字”热搜词里有“waf拦截字符串mysql关键字过滤”这其实是个经典误区。早期WAF规则喜欢把select、union、information_schema、sleep这些MySQL关键字作为拦截特征确实能拦住一些低级攻击但问题很多一是误报高正常业务参数里都可能出现这些词二是绕过容易比如大小写混合SeLeCt、注释/***/、URL编码%73%65%6c%65%63%74都能轻松绕过去。更科学的方法是做语义分析。在自写规则时你至少要兼顾三个层面关键字匹配作为兜底但要加“位置限定”比如只在特定的参数名id,keyword里检测而不是全URI扫描。编码识别WAF在匹配前必须对参数做URL解码、HTML实体解码、二次编码解码。防止%27单引号绕过。攻击特征的正则建模不要匹配单词而是匹配语法结构。比如SQL注入常见特征是“引号闭合尝试联合查询”你可以用正则(\|\)\s*(or|and)\s*\w\s*(|||like)之类的模式虽然也会误报但比裸关键字高明得多。我自己写SQL注入规则时会先在日志里挖一个月真实攻击样本统计出高频payload再针对性写规则。比如现在很多自动化工具喜欢用polyglot多语言混合payload特征是/*!50000union*/select这种MySQL特性正则写成/\*!\d{4,6}\s*(union|select|insert|update|delete)/i实测效果很好。2.3 攻防博弈WAF绕过常用手法与对应的防御规则WAF规则写完之后一定要做“绕过测试”。不是拿别人的工具打而是模拟攻击者绕过你的WAF。我列一个典型的绕过清单每条都对应一个防御要点大小写/注释混淆UnIoN SeLeCt、UN/**/ION/**/SEL/**/ECT。防御匹配前统一转小写并移除SQL注释包括MySQL的/*! ... */内联注释。URL编码/二次编码%27%20or%2011。防御多次解码至少解码三次如果业务会做二次解码则要解到业务层。json/表单嵌套POST body里用JSON格式参数名和值都做了Base64编码。防御规则引擎需要支持JSON解析解析后在参数值里匹配。分块传输Chunked Transfer-Encoding攻击者把payload拆成多个chunk每个chunk单独发送绕过WAF的body检查。防御WAF必须支持chunked解码否则所有基于规则的body检测都是摆设。这点很多自研WAF会忽略。Unicode/混淆编码比如/%u006f%u0072。防御支持Unicode解码或直接禁用非标准编码。对应到规则编写我的经验是“抓大放小”。不要试图写出一种规则防住所有绕过而是做“多级规则”第一级是基础特征阻挡低水平攻击第二级是异常行为检测比如同一IP在短时间内触发多次拦截直接封IP第三级是业务规则兜底如登录接口强制校验验证码。2.4 规则生命周期管理从草稿到退役规则不是写完就完事了。我见过太多团队规则越堆越多最后连作者自己都看不懂。所以一定要建立规则的生命周期管理草稿阶段先看规则是否能识别测试payload用curl构造攻击样本验证。观察阶段在日志里标记但不拦截观察一周统计命中次数和误报样本。启用阶段确认误报率低后开启拦截。维护阶段每季度复查规则攻击手法变了就更新规则命中率长期为0的考虑删除。这个流程一定要落到文档和版本控制里。文本型规则ModSecurity规则可以用Git管理雷池这类图形化规则也能导出导入。安全防御体系的核心之一就是“可追溯”不然出了事根本没法复盘。3. 防护策略定制从单点到体系3.1 策略分层基础防护、主动防御、业务安全很多WAF产品自带“策略模板”一键开启就算完事。但真正的策略定制至少要分三层基础防护策略通用攻击类型拦截如SQLi、XSS、命令注入。这部分用规则集开箱即用但需要定期更新规则库。主动防御策略基于行为特征比如IP信誉、地域封禁、频率限制、会话异常。因为攻击者老换IP和payload静态规则拦不住要用动态行为模型。业务安全策略针对具体业务逻辑比如登录接口的滑块验证、订单金额范围校验、上传文件的二次安全检查文件头、内容熵。这部分WAF的原生能力往往不够要配合业务代码实现但WAF可以做前置校验。以登录接口为例策略可以这样配置同一IP 5分钟内超过10次登录失败直接封禁1小时请求头中User-Agent为空或批量工具特征如sqlmap、python-requests触发告警并进入验证码流程登录参数中带SQL注入特征直接拦截并拉黑IP。这些策略不是零散加的而是在WAF控制台统一配置按服务域名路径维度区分。3.2 按业务场景定制规则API接口、文件上传、后台管理定制策略的核心是按场景分类不要一把梭。以下是我实际项目里常用的几个定制方案仅供参考API接口现代业务大量使用前后端分离API请求的Content-Type通常是application/json。基础WAF规则往往只检查表单格式对JSON解析不全。因此要么选支持JSON解析的WAF要么在规则中显式提取JSON字段。比如在ModSecurity中写SecRule JSON:username pm attack这样才能准确匹配到JSON里的攻击载荷。另外API接口还要控制HTTP Method只允许GET/POST其他方法直接拒绝。文件上传功能上传接口是重灾区。WAF除了检查文件后缀名还要检查文件内容签名。比如图片文件要验证JPEG/PNG的文件头防止攻击者把一个PHP脚本改成.jpg上传。如果WAF支持还可以对上传内容做“恶意代码扫描”但性能开销较大建议在业务层补充。后台管理路径后台路径/admin、/manage等可以直接用单独策略禁止非内网IP访问、强制二次认证、对每个请求都校验Cookie中是否有特定标记。在WAF上做IP白名单会比在应用里做更早挡掉危险流量。3.3 与CDN、源站联动以山石WAF反向代理为例“山石WAF配置反向代理”是热搜里的一个词其实山石这类硬件WAF配置反代流程都差不多先创建一个“服务器组”填源站IP和端口再创建“虚拟服务器”绑定WAF的外网IP和域名把流量转发给服务器组。类似思路也适用于雷池、NginxModSecurity。注意事项有几点第一确保WAF到源站的连接使用内网或安全通道避免源站IP暴露第二如果源站启用了HTTPSWAF需要配置证书或做SSL卸载这会涉及私钥保管的问题一定要限制访问权限第三源站要只允许WAF的IP访问。比如在安全组或iptables里限制80/443端口只对WAF开放这样即使攻击者知道源站IP也直接撞墙。很多团队漏了这一步WAF变成摆设。3.4 误报处理与灰度上线误报是WAF策略的“日常难题”。我见过最夸张的一次一条规则把优惠券名称中含“CVE”的请求全拦截了因为规则把“cve”当成了命令注入特征。解决误报有三个关键动作设置“仅记录”模式新规则先记录不拦截收集样本确认无误后再切换拦截。编写白名单规则针对确定的正常业务参数可以放行部分检测项。但要谨慎白名单写得太宽等于给攻击者开了后门。大键盘灰度把新规则先应用在一个测试域名或低流量节点观察效果后再全量部署。还有就是要定期清理“僵尸规则”。很多规则长期不更新可能产生错误判断。我在每次版本更新后都会统计每个规则的命中次数、白名单命中次数用报表驱动规则优化。4. 保姆级教程在Ubuntu 22.04上通过Docker Compose一键部署雷池WAF社区版4.1 准备工作一台干净的Ubuntu 22.04服务器建议配置2核4G以上磁盘20G以上。如果你只是测试一台虚拟机也够。先更新系统sudo apt update sudo apt upgrade -y然后安装Docker和Docker Compose插件以下命令在Ubuntu 22.04测试通过sudo apt install docker.io docker-compose-v2 -y sudo systemctl enable --now docker docker --version docker compose version如果系统没有docker-compose-v2也可以用传统方式安装Docker Engine这里不详述。确保Docker正常启动后进入下一步。4.2 获取雷池社区版配置文件雷池官方提供了一套Docker Compose部署方案核心文件是compose.yaml。我这里的思路是拉取官方镜像然后写一个精简的docker-compose.yml。先创建一个工作目录mkdir -p /opt/safeline cd /opt/safeline然后创建docker-compose.yml内容如下版本以官方为准如果版本更新请自行调整services: safeline-mgt: image: chaitin/safeline-mgt:latest container_name: safeline-mgt restart: always volumes: - ./data/logs:/logs - ./data/mgt:/app/data - /var/run/docker.sock:/var/run/docker.sock environment: - SAFELINE_DIR/opt/safeline ports: - 9443:9443 - 8000:8000 networks: - safeline-network safeline-detector: image: chaitin/safeline-detector:latest container_name: safeline-detector restart: always volumes: - ./data/detector:/app/data - ./data/logs:/logs networks: - safeline-network depends_on: - safeline-mgt networks: safeline-network: external: true这里我把管理端口9443和检测端口8000映射出来了。注意先创建外部网络docker network create safeline-network然后启动容器docker compose up -d启动过程中拉取镜像可能比较慢耐心等待。如果一切正常docker compose ps应该能看到两个容器都在运行。4.3 初始化登录管理界面并配置防护站点默认情况下雷池管理面板跑在https://服务器IP:9443。第一次访问会提示设置管理员密码。这里有几个注意点密码必须足够复杂否则管理面板本身就是个风险点。管理面板不要暴露在公网建议只允许内网IP访问或者在安全组限制来源IP。登录后进入“站点管理”添加你的业务域名和源站地址。比如源站是http://192.168.1.10:8080域名填www.example.com勾选“自动接入”。雷池会自动生成Nginx反代配置并让流量经过WAF。此时你不需要动源站的NginxWAF会作为反向代理接管流量。如果你源站本身也开了HTTPS需要注意证书配置避免证书链报错。4.4 自定义规则亲手拦截一个“mysql关键字”注入测试我们现在来做一个小实验验证WAF规则能拦SQL注入。先在雷池控制台左侧找到“防护策略”-“自定义规则”新建一条规则规则名称测试SQLi匹配字段包含参数名为id的请求参数匹配条件参数值匹配正则(?i)(union|select|sleep|information_schema)动作拦截命中次数限制无保存后我们用curl构造一个攻击请求curl -k -s https://你的WAF地址/test?id1%20union%20select%201,2,3如果你配置正确响应码应该是403并且雷池日志里能看到这条请求命中规则。这就是一个最基础的“mysql关键字过滤”场景。但要注意上面这条正则只是演示。实际生产环境光这样写会被绕过大小写、注释等你还要加上更细的规则并配合雷池自带的语义分析。雷池内置的语义分析引擎对SQL注入的识别效果比纯正则好很多建议开启“智能检测”模式。4.5 日志与告警让WAF的每一次拦截都留下痕迹防护体系不能只“拦”不“看”。雷池控制台有“攻击事件”页面可以按时间、攻击类型、源IP查看拦截记录。我建议设置第三方告警比如通过Webhook把攻击事件推到企业微信或飞书。在雷池控制台找到“告警配置”填上你的Webhook地址选择触发条件“高危攻击事件”。日志保存这块雷池默认把日志放在挂载目录./data/logs下。如果业务量大建议把日志接入ELK或Loki做长期留存和溯源分析。WAF日志是安全运营的重要数据源不能只留在容器里否则容器重启就丢了。4.6 高可用与备份雷池容器单点跑在服务器上如果这台服务器挂了业务就全挂了。所以生产环境建议部署两个WAF节点前面再架SLB负载均衡做健康检查或者直接用云厂商的高可用WAF。如果是自建的最简单的方式是用Keepalived做虚拟IP两台WAF做主备。另外定时备份WAF配置。雷池的配置存储在./data目录直接用tar打包到其他存储即可tar czf /backup/safeline_$(date %F).tar.gz -C /opt/safeline data恢复时解压到原目录再docker compose restart即可。定期做一次恢复演练确保备份可用。5. 安全防御体系搭建WAF之外还能做什么5.1 WAF不是防御体系的全部别把宝押在一个点上我在实际项目中见过不少团队买了WAF就以为安全了结果源站代码本身有漏洞WAF被绕过后仍然被拖库。纵深防御才是正道WAF负责应用层入口防护但网络层要有安全组和ACL主机层要有HIDS主机入侵检测和基线扫描数据库要有访问控制和审计数据要有备份和加密。各层职责不同WAF挂了还有下一层兜底。比如之前有次应急响应攻击者绕过了WAF利用分块传输绕过打到了源站的命令注入漏洞。但因为主机上装了HIDS攻击者的shell命令被实时告警我们才及时切断了攻击。WAF和HIDS的告警联动才是完整的检测能力。5.2 用AWS WAF等托管服务扩展云上防护如果你的业务在AWS上那AWS WAF是很好的补充。它天然集成在ALB、CloudFront、API Gateway前无需自己部署反代非常适合云原生架构。AWS WAF规则有两种一种是托管规则组AWS Managed Rules开箱即用包括常见威胁的防护另一种是自己写的自定义规则使用JSON格式支持AND/OR/NOT逻辑。比如你可以创建一个IP集封禁恶意IP再创建一个字符串匹配规则在请求体中检测攻击特征。AWS WAF的Web ACL可以关联多个资源集中管理。但要注意AWS WAF按规则数量和请求量计费规则太复杂会增加成本。我建议在云上只做“粗粒度拦截”细粒度交给业务侧或自建WAF。5.3 从被动拦截到主动防御情报与协同搭建安全防御体系不能只依赖攻击发生时的规则。我们要引入威胁情报定期拉取恶意IP库、恶意域名列表把它们同步到WAF和防火墙。比如每天凌晨更新一份威胁情报IP段在WAF上自动生成封禁规则。现在很多WAF产品支持“动态情报联动”雷池社区版也内置了高可用IP封禁功能。同时把WAF日志和其他安全设备日志统一到同一个SIEM平台做关联分析。比如WAF在凌晨2点拦截了一波扫描同一时段内还有一个源IP的主机登录异常这两条日志关联起来可能就是一个完整攻击链。眼见为实这一步非常重要。5.4 持续对抗WAF Bypass更新规则的节奏安全攻防是持续的不存在“配一次就永逸”的方案。我的经验是每两周例行检查一次规则库更新每季度做一次绕过测试。具体做法是收集最新的攻击payload可以通过Github上的payload项目、安全社区的文章但要注意合规只用于自家系统测试在测试环境跑一遍看WAF拦截率。如果发现漏网就需要调整既有规则或新增规则。这里需要提醒一下WAF绕过测试要严格遵守授权范围只对自己公司业务做不要拿别人线上系统练手。这是职业底线。6. 常见问题与排查技巧实录6.1 正常业务被误拦截了怎么快速定位误报是常态。当业务反馈“某个请求被拦了”先别急着删除规则按这个顺序排查去WAF日志找到对应时间点的拦截详情看是被哪条规则拦的。提取出被拦的原始请求删掉攻击特征换上正常参数重新发一次确认是规则问题还是业务问题。如果确认误报是普遍性误报把规则从“拦截”改为“观察”是个别特殊参数误报则在规则加白名单条件比如排除特定URI。记录issue定期复盘优化规则集。记住一个原则WAF规则宁可漏不可误。漏了还可以靠其他层补救误了影响业务到最后会被业务部门强烈要求关停WAF那就真成摆设了。6.2 WAF Bypass测试如何验证自己的WAF靠谱做Bypass测试时我一般会用三个工具思路用Burp Suite的Intruder把多个payload分别编码URL编码、大小写、注释、JSON格式批量发送看状态码。手动构造分块传输、Multipart混合等畸形HTTP请求观察WAF是否完整解析。使用sqlmap的--tamper参数生成绕过payload测试WAF对SQL注入的防护能力。测试后发现绕过不要慌建议把绕过的payload作为“样本特征”加进规则集。这种“以战养战”的方式规则会越来越完善。6.3 WAF性能下降了肿么办WAF作为反代确实会增加一定的延迟通常1-5ms但如果页面明显变慢就要检查规则数量过多或正则效率低尤其是“灾难性回溯”的正则在请求量大时CPU会被打满。优化方式减少正则嵌套用字符串匹配代替部分正则匹配。日志写入阻塞在日志量大的时候磁盘IO容易成为瓶颈。建议把WAF日志放到独立磁盘或者单独存储。源站连接复用确认WAF到源站的Keep-Alive是否生效否则每个请求都要新建TCP连接延迟自然上去了。性能优化不是一句话的事但思路就是“常见的性能瓶颈八成在规则和日志不要先怀疑设备性能”。6.4 排查工具与技巧速查推荐几个我常用的排查工具curl -k -X POST -d id1 union select 1 https://waf_ip/test快速测试规则效果。docker logs --tail 200 safeline-detector查看雷池检测容器的日志。tcpdump -i eth0 port 80 -A抓包看实际流量是否进入WAF。Burp Suite 的 Logger 插件记录所有请求方便回溯。你在做规则验证时记得用真实的HTTP客户端而不是浏览器因为浏览器会做各种预请求干扰测试结果。写到最后安全防御这条路我踩过的坑远比写出来的多。WAF规则编写、防护策略定制、安全防御体系搭建每一环都要贴近业务不能照搬模板。我个人体会最深的一点是规则的精髓在于“克制”不要追求拦截一切而是要从日志和数据里找到真正值得拦截的流量把误报压到最低。另外一定要在自家环境里反复做WAF绕过测试越知道攻击者怎么想你的防线才越扎实。希望这篇实战内容能给你一些借鉴少走几步弯路。
返回列表