
1. XSS防护思路与WAF规则组大概三周前我在给一个客户调XSS防护策略时又遇到了那个经典问题到底用域名精确匹配还是直接用通用防护覆盖全部流量客户的应用同时挂着主站、接口站和管理后台每次有人被误导说“通用防护会误伤业务”就全站下线规则结果XSS攻击流量直接从缺口里进去了。这类问题在维护云WAF时特别常见今天就把域名精确匹配和通用防护的差异、适用条件、配置方法、误报与绕过这几个点完整拆一遍给正在做WAF策略的同学一份可以直接照做的参考。1.1 为什么XSS防护离不开WAFXSS跨站脚本攻击的麻烦之处在于真正的攻击代码是在用户浏览器里执行的。攻击者把一段恶意的JavaScript塞进输入框或URL参数应用如果不做输出编码这段脚本就会在别人的浏览器上下文里跑起来偷Cookie、改页面、模仿用户操作什么都有可能做。很多研发团队在代码层做了过滤但过滤函数总有漏网之鱼尤其是在富文本、JSON接口、URL回调这类场景里稍微漏一处就等于把大门打开。WAF的价值在于它站在业务代码前面。正常情况下流量先过WAF再进源站WAF在HTTP报文里做模式匹配和语义分析发现XSS特征就直接拦截不需要业务方停机上版本。对外部攻击者来说他看到的是一道不可绕过的前置关卡对内部研发来说少了一部分安全代码的返工。所以说XSS防护不是有了WAF就万事大吉但绕开WAF直接让应用裸奔在今天的互联网环境下非常危险。1.2 托管规则组与自定义规则的边界云WAF里通常有两类XSS防护能力。一类是托管规则组也就是安全厂商提前写好并维护的规则包里面除了XSS还有注入、文件包含、恶意Bot、爬虫防护等。这类规则组的好处是省心开通后只要关联到Web ACL就能生效规则引擎会自动更新坏处是黑盒——你只知道它拦截了但不知道具体哪条规则命中误报时不好解释。另一类是自定义规则由你自己根据域名、路径、Header、Body内容来写匹配条件动作可以是Block阻断或Allow放行。自定义规则灵活但非常依赖配置者的经验。这里要引入两个基础概念Web ACL和规则优先级。可以把Web ACL理解成一套完整的安全门禁策略里面放着若干个规则或规则组。流量到达WAF后按规则顺序一条一条匹配优先级用数字表示数字越小越先执行。先命中的规则决定请求是放行还是阻断。域名精确匹配和通用防护本质上都是围绕这套优先级体系在做文章它们不是不同的产品功能而是不同的编排思路。2. 域名精确匹配与通用防护两条路线到底差在哪2.1 域名精确匹配把规则锁死在指定域名域名精确匹配的意思是在自定义规则里加一个Host条件明确写出只对某个具体域名生效。比如我用admin.example.com作为匹配值规则就只检查访问这个域名的请求主站或其他子域名的流量完全不碰这条规则。如果用后缀匹配再勾上example.com所有二级子域都会被命中而精确匹配模式连二级子域都不沾只有完全一致的域名才触发。这种方案最适合需要严格区分业务边界的场景。比如企业内部平台有独立的审计域名或某个接口因为历史原因无法修改输入格式只允许特定域名被严格检测。精确匹配还可以配合路径、请求方法、来源IP一起用比如我只对admin域名的POST请求做XSS拦截其他请求放行这能有效减少误报。但这个方案有个容易翻车的点Host头经过CDN或负载均衡之后必须原样传给WAF。有的链路在回源时把Host改成了内网IP或者默认域名精确匹配就会全部落空。我第一次配这种规则时就遇到过最后排查半天发现不是规则没下发而是源站前面的代理改了Host。所以做精确匹配之前一定要先确认整条链路的Host透传是正常的。2.2 通用防护一套规则覆盖全部流量通用防护则是把托管规则组或自定义规则直接关联到整个Web ACL对当前接入WAF的所有域名统一生效。只要域名完成了DNS接入流量进入WAF就会被同一套规则检测。它更像是园区大门的保安不管你是谁进入前都要过一遍安检精确匹配则是每栋楼门口再设一道专属门禁。通用防护的优势很明显。第一新接入的域名不用逐个配规则Web ACL关联的资源里加入这个域名就自动有防护这对业务发展快的团队特别友好。第二规则统一管理安全策略收敛在一处审计也不用面对几十条散落的规则。第三基线兜底哪怕某个域名被遗漏在“重点监控名单”之外也有基础防护兜着。缺点同样不能忽视。规则对所有域名生效意味着某个域名的特殊参数格式可能让规则误判把正常请求当成攻击。一旦这条规则出了问题影响范围是整个Web ACL里的所有域名。我在实际工单里见过有团队为了一个接口的富文本需求直接把托管规则组的XSS部分全部改成放行结果整个站点的XSS防护都失去了意义。这就是通用防护的“大锅”属性——覆盖面大但精细度不足。2.3 选型判断的三个关键维度选域名精确匹配还是通用防护我建议看三个维度覆盖面、误报容忍度、运维精细度。维度域名精确匹配通用防护防护覆盖面只覆盖配置的域名容易留盲区所有接入域名全覆盖新增域名自动防护误报控制可精准限定域名/路径/方法误报面小整站生效一个误报影响所有域名上线速度需要逐条配置规则耗时较长关联规则组即可快速上线日常维护规则多需要逐个维护集中在Web ACL统一管理合规审计可按域名独立追踪策略策略简单但域名间无法差异化基于这三个维度我个人的默认策略是新建WAF一律先用通用防护把托管规则组挂上以Block或统计模式上线跑几天然后根据日志命中情况对核心域名、敏感后台、易误报的接口再加精确匹配的Allow或Block规则。也就是说通用防护解决“有没有的问题”精确匹配解决“准不准的问题”两个不是互斥对立而是顺序配合。3. 实操配置一步步搭出两套方案3.1 前置准备工作清单开始配置前先把链路信息理清楚不然后面调规则就是盲人摸象。第一域名要已经接入WAF通常是通过DNS CNAME把流量切到WAF节点或者在负载均衡上关联Web ACL二选一就好。第二确认源站的Host透传正常如果前置有CDN或反向代理一定要在转发配置里保留原始Host头。第三打开WAF日志至少保留HTTP请求的域名、URL、规则ID、动作、来源IP和Body片段。很多团队把日志功能省略了理由是流量不大等出问题了再开。这个想法很危险。误报和漏报的排查完全依赖日志没有日志你只能猜是哪条规则拦截的。我在调WAF时一般会同步把日志接到日志服务再配一个简单的按规则ID聚合的看板这比在控制台里一页一页翻记录靠谱得多。3.2 精确匹配XSS规则用Host条件圈定范围第一步创建Web ACL把需要防护的资源关联进去。第二步在规则列表里选择自定义规则名称建议带上业务标识比如xss-strict-admin方便后面日志里认出来。第三步设置第一个条件Host等于admin.example.com第四步选择XSS匹配如果你不想写具体特征可以直接引用托管规则组里XSS规则或者选择按Body/Query统一检测。第五步动作设为Block优先级写一个较小的数字例如5。下面是一个示意性的规则结构各云厂商的JSON字段会略有差异但逻辑是通用的{ Name: xss-strict-admin, Priority: 5, Action: Block, Statement: { And: [ { FieldToMatch: { Type: HEADER, Name: Host }, MatchValue: admin.example.com, Operator: EXACT }, { XSSMatch: { FieldToMatch: { Type: BODY }, TextTransformations: [NONE, URL_DECODE, HTML_ENTITY_DECODE] } } ] } }这里想提醒一句不要把XSS检测范围只放在查询参数里POST请求的Body才是重灾区。有的同学只检测Query String攻击者把payload挪到JSON Body里就绕过了。所以我建议在精确匹配规则里把Body也纳入检测同时开启URL解码和HTML实体解码避免编码绕过。3.3 通用防护XSS规则基于托管规则组快速覆盖通用防护的配置更简单。创建Web ACL关联资源后在规则组管理里添加托管规则组选择包含XSS检测的核心规则集动作设为Block即可。这里我建议先把动作设置为Count仅计数不拦截跑一天用日志看看有多少正常请求会命中再切到Block。不要一上来就严格拦截尤其是老业务你不知道遗留系统里有多少不规范的输出直接Block可能引发大量工单。另外托管规则组会自动更新版本这是优点也是风险。厂商更新规则时可能加入更激进的检测逻辑导致你某个个性化接口突然被误杀。所以我习惯在规则组里开启版本管理测试环境先验证新版本再应用到生产Web ACL。如果发现新版规则误报可以先锁定旧版本同时尽快让业务方整改参数格式。3.4 规则叠加与优先级设计生产环境很少只挂一套规则。最常见的组合是通用防护的托管规则组作为大网精确匹配的规则作为网格。下面是我常用的一套优先级设计优先级规则类型动作说明1特定管理后台XSS检测Block只对admin.example.com生效5富文本接口白名单Allow限定host为www.example.com且路径以/api/rich-content开头10核心规则集含XSSBlock对所有接入域名兜底100默认放行Allow未命中任何规则时正常通行这里有个非常容易踩的坑Allow豁免规则的优先级必须比触发误报的Block规则更高。如果你想放行某个接口但Allow规则优先级数字比Block大流量会先被Block规则命中你的放行根本没有机会执行。我见过不止一次同事改了Allow规则后业务还是被拦截最后发现是优先级写反了。4. XSS检测原理与误报实战4.1 XSS规则到底在检测什么云WAF的XSS规则一般会覆盖几类特征脚本标签比如scriptalert(1)/script事件处理属性比如img srcx onerroralert(1)危险协议比如javascript:还有一些基于上下文的分析检测HTML标签属性里的可执行代码。为了对抗编码绕过WAF通常会把URL编码、HTML实体编码、Unicode编码解码后再做匹配这也是为什么一个payload可能同时命中好几条规则。这种检测逻辑决定了误报的必然性。只要请求里出现类似的字符串WAF就会报警它不会像人一样理解这是不是一段展示用的代码示例。很多技术网站本身就会在文章里贴代码片段如果业务上允许这类内容通用规则很容易误杀。想控制误报只能在规则范围上做文章也就是回到我们前面讲的精确匹配。4.2 精确匹配如何降低误报真实场景举个例子一个内容社区的主站允许用户在评论里发简单HTML例如a href#点这里/a。通用防护规则组会把href属性、标签结构当作XSS特征导致用户正常评论被拦截。运营团队天天投诉开发也没办法因为这是业务硬需求。这时候如果采用域名精确匹配把通用规则的作用域限定在不允许富文本的外部输入域名上同时给主站评论接口单独加一条Allow豁免并限定Host、路径、方法那么正常评论能发出去其他域名依然保持严格防护。看起来很简单实际操作要特别注意Allow豁免不能把所有域名一刀切否则攻击者把恶意脚本移到同一个路径照样能绕过检测。4.3 通用防护的绕过风险不是挂上就万事大吉挂上通用防护不等于一劳永逸。XSS攻击的变形非常多大小写混写、Tab符号分隔、Unicode编码、JSON嵌套、分块上传都可能逃过签名检测。托管规则组虽然更新频繁但永远跟不上手工构造的绕过姿势。我平时做安全巡检会准备一批测试payload手动重放到WAF上看看哪些能被拦截哪些能穿透穿透的再写自定义规则补齐。更值得警惕的是“规则空转”。有些团队因为通用防护误报太多直接把规则组的动作从Block改成Count美其名曰先观察。结果一直没看日志等于全站裸奔。规则还在其实什么都没拦。通用防护的价值建立在动作有效的前提下如果被误报吓怕了宁可引入精确匹配来纠偏也不要把大网整个关掉。5. 案例复盘某平台的XSS防护整改5.1 环境与需求背景下面用一个虚构的整改案例说明完整流程。某内容平台有三个域名www.example.com是用户主站页面里允许富文本open.example.com是对外的接口域名接了不少第三方回调admin.example.com是管理后台访问量小但权限敏感。客户反馈主站发文章时经常被WAF拦截运营效率受影响同时安全团队又怀疑最近有XSS攻击进入了管理后台。我先调了日志发现主站被拦截的基本都是正常带HTML标签的正文后台确实有少量请求触发了XSS规则但因为当时规则组的动作已经被人改成Count攻击请求实际没有被阻断。这两个问题叠加在一起就是典型的通用防护和精确匹配没有配合好。5.2 整改方案先通用后精确整改第一步把托管规则组动作恢复为Block先恢复全网基线第二步为富文本接口创建精确匹配的Allow规则条件是Host等于www.example.com路径以/api/rich-content开头方法限定POST同时确保这条Allow规则的优先级高于通用Block规则第三步为admin.example.com单独加一条精确匹配XSS Block规则并且路径覆盖到所有管理接口第四步把日志中Block请求按规则ID聚合找出被误杀的正常业务逐个加白或修改业务参数。这套方案的思路是让大网兜底让精细规则做局部调整。我不会简单地说“用精确匹配代替通用防护”因为新域名、新接口随时可能上线没有大网就等于没有默认安全。精确匹配解决的是大网照顾不到的业务细节。5.3 踩过的坑与最终效果这个项目里踩过一个很典型的坑。给富文本接口加Allow规则时同事只写了路径条件漏了域名条件导致所有域名下/api/rich-content这个路径都被放行。攻击者尝试通过www.example.com的另一个域名或IP直接访问接口时XSS检测直接被绕过。后来我们在Allow条件里补上了Host精确匹配并且测试时验证了其他域名访问同一路径仍然会被Block。最终效果我用一批常见攻击payload重放svg/onloadalert(1)、编码后的javascript:都被拦截同时正常富文本发布、历史文章编辑都没有再被误杀。这个结果也说明精确匹配和通用防护不是“哪个更好”的关系而是“哪个更合适”的关系。6. 常见问题与排查技巧实录6.1 精确匹配规则明明配了为什么不生效大多数情况是Host实际值和规则条件对不上。你先在日志或者用curl看请求到达WAF时带的Host头是什么如果前面有CDN把Host改了那后端看到的就不是你预期的域名。其次检查Web ACL是否真的关联到了资源很多云厂商控制台资源列表和Web ACL的关联关系不是自动同步的。最后看规则优先级如果有其他Allow规则优先级更高Block规则根本不会被评估。排查动作我一般按固定顺序看访问日志里请求有没有进入Web ACL评估匹配到了哪条规则动作是什么如果没有日志再临时在WAF上开一个统计规则来抓特征。直接瞎猜很容易浪费时间。6.2 通用防护误杀接口如何放行而不留后门第一步从日志里找到被Block请求命中的规则ID和原因第二步写一条精确匹配的Allow规则同时限定域名、路径、请求方法甚至请求头来源第三步把Allow规则的优先级数字调小到对应Block规则之前第四步上线后用正常请求和攻击payload各测一遍确保正常放行、恶意拦截。注意不要直接在托管规则组里把那一条XSS检测规则全局禁用。你在这个Web ACL里关联的所有域名都依赖它全局禁用的后果是把威胁暴露给所有业务。我看过太多这种图省事的操作最后都是给自己挖坑。6.3 规则优先级和动作的默认逻辑云WAF优先级基本都遵循一个约定数字越小越先执行。假设有一条优先级为1的规则放行所有流量后面优先级为100的Block规则永远不会执行。这个顺序很容易被忽略尤其是前后加规则的时候。我建议把优先级当成目录来维护低数字留给明确的Allow豁免和关键Block中数字放通用规则组高数字放最后兜底。改动优先级之前先问自己三个问题这条规则是放行还是阻断它会不会覆盖更严格的规则影响范围是不是只有预期的那几个域名带着这三个问题改能少掉许多事故。6.4 日志与告警的排查技巧处理WAF问题最忌讳只看控制台的总拦截数。我会把日志字段按请求ID关联起来看Host、URI、规则ID、动作、来源IP、User-Agent、Body前几千字节。当某一类正常请求频繁命中某条规则时用重放工具把原始请求发到WAF的测试接口能看到具体命中原因。误报调优的整体思路是先允许再限制而不是先限制再排除。先用统计模式收集数据再切Block再把正常的请求精确Allow。告警不要只发邮件很多团队的邮件根本没人看可以接即时通讯机器人按严重级别分发。不过告警词里不要只写次数要把命中的路径和规则ID带出来否则运维收到告警还得自己翻系统。6.5 XSS防护调优的个人经验我在实际维护WAF过程中最深刻的体会是规则配置不是上线就结束而是一个持续迭代的工程。每次业务版本更新都应该顺手看一遍新接口的日志每季度可以做一次针对XSS常见payload的回归测试。所有Allow豁免规则都要写清楚用途和维护人否则三个月之后没人知道为什么放行这个路径也不敢删就会变成一个越来越厚的历史包袱。最后再分享一个被验证过很多次的方法新域名上线时先确认它已经被通用防护兜住再去想要不要加精确匹配。如果你把安全策略写成了一堆散落的精确匹配规则新的攻击面反而可能出现在你根本没写规则的地方。先有兜底网再做精加工这个顺序记牢了WAF的坑能少踩一半。