WAF对跨站脚本攻击的过滤原理并不神秘,本质上就是“检查-匹配-处置”三步走,但它拦不住所有XSS,绕过风险主要出在解析差异和规则缺陷上。
WAF对XSS攻击的过滤原理
WAF(Web应用防火墙)拦截XSS攻击,靠的是在HTTP请求到达服务器之前,先对数据做一道安检,这道安检分两条技术路线:基于规则的正则匹配和基于语义的解析检测,目前市面上的主流WAF产品,包括云WAF、硬件WAF和软件WAF,绝大多数都采用“规则为主、语义为辅”的混合架构。
基于规则的正则匹配
这是WAF最传统、也是目前覆盖率最高的检测方式,WAF内置一个庞大的攻击特征库,里面存着大量XSS攻击载荷的指纹,当请求参数、URL、请求头或Cookie中的数据经过WAF时,它会把这些数据与特征库里的正则表达式逐一比对。
典型的检测对象包括:
<script>、<img>、<svg>、<iframe>等危险标签alert()、confirm()、prompt()等敏感函数onerror、onload、onclick等事件处理属性javascript:、data:、vbscript:等伪协议document.cookie、location.href等敏感DOM对象charCodeAt、fromCharCode、String.fromCharCode等编码辅助函数
只要命中其中任何一条,WAF就会执行配置好的动作,常见的处置方式有直接阻断(返回403页面)、记录日志(只告警不拦截)和替换过滤(把危险字符替换成空或HTML实体)。
基于语义的解析检测
纯正则匹配在应对复杂攻击时非常吃力,比如用模糊字符干扰、多层编码嵌套、标签属性拆分等手段就能轻松绕过,近年来,不少WAF产品引入了语义分析引擎,也就是先解析、后判断。
语义分析会模拟浏览器的解析行为,把请求中的数据当作HTML代码去解析,构建出DOM结构,然后看解析结果里是否存在可执行上下文,举个例子,一个请求参数如果经过HTML解析后,出现了<script>标签且内部包含可执行JS代码,或者某个标签属性值被解析为javascript:协议,WAF就会判定为攻击。
这两种方式在思路上有本质区别:
| 对比维度 | 正则匹配 | 语义解析 |
|---|---|---|
| 检测原理 | 字符串模式匹配 | 模拟浏览器解析 |
| 准确率 | 误报高、漏报多 | 误报低、检出率高 |
| 性能消耗 | 低 | 高 |
| 对畸形 payload | 极易被绕过 | 有一定抗性 |
行业共识认为,纯正则的WAF已经很难应对当前的XSS攻击变种,语义分析正在成为主流WAF的标配能力,但即便是语义引擎,也绕不开一个根本问题WAF看到的和浏览器看到的未必一致。
WAF绕过XSS攻击的常见手法
WAF的过滤逻辑和浏览器的解析逻辑存在差异,这个差异就是绕过攻击的核心突破口,攻击者利用WAF和浏览器对同一段数据的理解不同,构造出WAF认为“安全”但浏览器会“执行”的载荷。
利用编码嵌套绕过检测
WAF扫描的是原始请求数据,而浏览器在解析HTML时会层层解码,攻击者利用的就是这个时间差。
最常见的操作是多重URL编码,WAF解码一次后发现还是<script>,但没继续解下去,而浏览器解了两层之后,变成了可执行的HTML,类似的手法还有:
- HTML实体编码嵌套,比如
<script> - Unicode编码绕过,利用
u003c这类JS层面的转义 - Base64编码配合
data:协议执行
有些WAF只检测<script>这种字面量,遇到%253Cscript%253E这种双重编码就傻眼了。
脏数据注入绕过正则
正则匹配的典型弱点是它可以被噪音干扰,很多正则表达式写得很严格,比如精确匹配<script>,那攻击者就插入一堆无关字符来破坏匹配。
在标签内部插入空字符、注释符、换行符、Tab符,
<scr<script>ipt>WAF找不到完整特征,浏览器解析时却会忽略掉中间的<script>字样,最终执行外层标签<img src=x onerror=alert(1)>改写成<img src=x onerror=alert//(1)>JS注释符干扰函数名匹配- 在事件属性值中插入
n、t等空白字符,部分正则的s匹配范围不够就会漏掉
这种手法本质上是考WAF的特征库覆盖度,规则写得不全,特征写得不够宽,就会被脏数据糊弄过去。
协议与解析差异绕过
这类手法利用的是WAF和浏览器对协议解析方式的不同,经典的案例包括:
data:text/html,<script>alert(1)</script>WAF只匹配javascript:协议,没把data:列进去java script:空字节截断,老版本Tomcat和部分WAF会栽在这里- 大写变小写、全角变半角,比如
JaVaScRiPt: - 利用浏览器的容错特性,比如
<svg/onload=alert(1)><svg>标签后直接跟再跟事件属性,WAF如果没适配SVG标签就会漏
等价替代与语法变形
更聪明的攻击者干脆绕开WAF重点盯防的标签和函数,改用等价手段。
- 用
<details ontoggle>、<marquee onstart>等冷门事件标签 - 用
document.write、eval之外的方式执行,比如Function构造函数、setTimeout字符串参数 - 用
String.fromCharCode(97,108,101,114,116)替代alert字面量 - 利用
window["al"+"ert"]这种字符串拼接拆开敏感函数名 - 用逻辑运算符拼接,比如
alert(document.domain)改写成(1,alert)(document.domain)
这些变体数量庞大且持续更新,WAF的特征库要追上新变体的速度,本质上是一场军备竞赛。
实际场景中的绕过案例复盘
很多站长遇到过这种情况:WAF日志里没有任何拦截记录,但站内确实被植入了恶意脚本,复盘之后发现问题出在WAF检测范围和业务场景的错配上。
一个比较典型的高频场景是JSON接口和富文本编辑器,WAF默认检测query string和表单参数,但对Content-Type: application/json的请求体,浅层检测往往覆盖不到位,攻击者把XSS载荷放在JSON字段里,WAF扫不到,后端程序取出数据后未过滤就渲染到页面上,最终形成存储型XSS,据行业内的一份渗透测试统计,相当一部分存储型XSS都是通过JSON接口和POST body打进去的。
另一个场景是文件上传 + XSS的组合攻击,攻击者上传一个HTML或者SVG文件这两种格式里都能内嵌JavaScriptWAF对上传文件的内容检测力度一般弱于参数检测,再加上部分厂家的WAF对multipart/form-data格式的解析存在缺陷,导致恶意文件被正常保存到服务器,用户访问该文件时直接中招。
再有一个常见问题存在于CDN节点和源站WAF的规则不一致,有些站点前面挂了CDN,CDN自带基础过滤,而源站还有一套WAF,攻击者针对CDN的规则缺陷制作payload,CDN放行后,源站WAF又因规则不同没有二次拦截,这种多层防护之间的规则缝隙,反而比单层WAF更容易被利用。
降低XSS绕过风险的实际做法
靠WAF单点防御扛不住XSS,这是行业共识,真正有效的方式是把WAF当作防线之一而不是唯一防线。
配置层:让WAF规则更贴合业务
对接WAF时,不要直接用默认规则集了事,默认规则为了控制误报率,覆盖面和严格程度都比较保守,正确做法是:
- 根据业务实际使用的技术栈,开启对应的扩展规则(比如Nginx环境开启Nginx专属规则,Java应用开启Java专属规则)
- 对管理后台、搜索接口、评论提交等高风险路径,设置更严格的检测模式
- 开启WAF的攻击详情日志记录,便于事后溯源和规则调优
- 定期更新规则库或开启自动更新,多数云WAF支持远程同步最新特征
代码层:从根上消除漏洞
WAF再强,也只是止血,开发者侧的正确防护措施比任何绕过对抗都重要:
- 上下文感知的输出编码,这是OWASP推荐的核心方案,根据数据输出位置选择不同编码方式HTML标签内用HTML实体编码,属性值内用属性编码,JavaScript上下文内用JS编码,URL上下文内用URL编码,一套编码逻辑打天下,必然出问题。
- 输入校验,对用户提交的数据做白名单校验,而不是黑名单过滤,比如数字只能传数字,枚举值必须落在给定范围内,邮箱、手机号按对应格式严格校验。
- CSP(内容安全策略)兜底,配置
script-src 'self'来限制脚本加载来源,即使攻击载荷穿透了WAF和服务端过滤,浏览器也会拦截内联脚本的执行,据近年来多个安全团队的实践总结,CSP对存储型XSS的抑制效果非常明显。
测试层:绕过手段验证
WAF部署完后,用攻击者的思路做验证,而不是只跑一遍拦截测试就宣告上线,可以拿公开的XSS绕过payload库(比如PayloadsAllTheThings里的XSS部分)对WAF防护站点做一轮自测,重点观察以下请求是否能被拦截:
- 加了注释符和换行的变体
- 多重URL编码的载荷
- 冷门标签和事件组合
- JSON格式的POST请求体
如果测试中出现漏报,先把规则调严,同时在代码层做输出编码,双管齐下。
Q&A:WAF拦截XSS攻击的常见疑问
WAF能100%拦截所有XSS攻击吗?
不能,WAF是一条重要防线,但它基于规则或语义的检测逻辑始终与真实浏览器的解析存在差异,任何WAF都存在被绕过的可能,如果把防护完全寄托在WAF上,等于拿单点防御对抗持续演进的攻击手法,风险很大。
WAF误报正常业务请求怎么处理?
先查看拦截日志确认命中的是哪个规则,判断是真实攻击还是误判,如果是误判,可以在WAF控制台为特定URI或参数添加白名单例外,但添加前需确认该接口不接受用户可控输入渲染HTML,否则等于给攻击者开了一扇门,更稳妥的做法是修改触发误报的参数名或调整规则阈值,而不是直接放行。
云WAF和自建WAF在XSS防护上有区别吗?
有区别,云WAF以SaaS形式提供,规则库由厂商统一维护和更新,无需用户自己维护特征库和硬件,防护能力取决于厂商的规则质量和数据积累,性价比高,自建WAF可以深度定制规则和拦截策略,但需要投入人力和时间持续运营,对多数中小站点来说,选一款口碑稳定的云WAF组件,比自建更经济,效果也更可靠,最终衡量标准还是看规则更新频率和解析引擎的检测能力。
首发原创文章,作者:王坚,如若转载,请注明出处:https://idctop.com/article/632867.html





