页面已被WAF阻止请联系管理员
那天下午两点十七分,页面已被我盯着屏幕上那行白底黑字——“页面已被WAF阻止,阻止请请联系管理员”。联系没有403的管理冰冷,没有404的页面已被茫然,就这么一句,阻止请像小区门口保安拦下你:“访客登记了吗?联系找谁?让他下来接。”可我是管理这个网站的开发啊。刚改完一行配置,页面已被点了保存,阻止请刷新,联系然后自己把自己关在了门外。管理
WAF,页面已被Web应用防火墙。阻止请名字听着挺唬人,联系其实就是个过滤网。它不关心你是谁,只关心你发过来的请求长什么样。SQL注入的特征、XSS的脚本标签、路径穿越的../,这些它都认。问题是,它认得太死板了。我那次改的是一个搜索接口,参数里带了个select单词。对,就是“选择”那个英文词。WAF一看:select?SQL关键字!拦截。我哭笑不得,用户搜个“select model”都得被挡。
规则是死的,业务是活的
很多WAF默认规则集来自开源社区,比如ModSecurity的OWASP核心规则。这些规则写的时候,考虑的是通用场景。可你一旦做的是垂直行业,比如医疗、法律、内部ERP,参数里出现敏感词的概率高得离谱。我见过一个工单系统,用户提交“如何删除旧数据”,WAF把“删除”和“数据”组合判定为危险操作,直接阻断。用户以为系统崩了,运维以为被攻击了,最后发现是自家防火墙在抽风。
更麻烦的是误报之后的处理。页面只给一句“请联系管理员”,没给请求ID,没给拦截原因,没给时间戳。管理员是谁?可能是运维,可能是开发,可能早就离职了。用户只能截图发群里,然后一群人开始猜:是IP被封了?是Cookie丢了?还是参数里哪个字踩雷了?排查半小时,最后发现是WAF规则太激进。
绕过去,还是调回来?
有人选择加白名单。把某个URL、某个IP、某个参数名直接放行。这招快,但等于在防火墙上开洞。攻击者只要知道这个洞,就能针对性构造绕过。我见过最离谱的白名单,是把整个/api/目录放行了,因为开发嫌麻烦。结果呢?三个月后数据被拖库,日志里全是正常请求——WAF根本没看。
另一条路是调规则。把误报的规则ID找出来,降低敏感度,或者加例外条件。比如那条拦截select的规则,可以改成只拦截select * from这种完整语句。但调规则需要懂正则,懂ModSecurity的SecRule语法,还得有测试环境。小团队根本没这个人力和流程。于是大家宁愿重启服务,或者换个端口,假装问题解决了。
那句提示本身就有问题
“请联系管理员”——这是把责任推给了用户。用户做错了什么?他只是正常点击、正常搜索、正常提交表单。WAF拦了,说明WAF认为他像攻击者。那WAF为什么不告诉用户“你的请求包含敏感字符,请修改后重试”?为什么不告诉管理员“拦截了来自IP x.x.x.x的请求,规则ID 942100,参数名q,值包含select”?信息不对称,导致每一次拦截都是一次黑盒事故。
我后来在自己的项目里改了默认拦截页。加了一行:Request ID: { { uuid}},再加一行:Blocked by rule: { { rule_id}}。用户截图发过来,我三秒定位。就这么点改动,省下了每周至少两小时的扯皮。WAF不是不该拦,而是拦完之后得让人知道为什么。否则那句“请联系管理员”,跟“系统繁忙请稍后再试”一样,都是废话。
现在我看到那行字,还是会想起自己被关在门外的下午。只不过这次,我知道门锁的型号,也知道钥匙在谁手里。
